[모던JS입문] 12장 정규 표현식

Bora Im·2020년 5월 21일
1

모던JS입문

목록 보기
6/8

정규 표현식 (Regular Expression)

  • 문자열의 패턴을 표현하기 위한 도구 💡
  • 문자열에 대한 강력한 패턴 매칭 기능 제공
  • 특정 패턴과 일치하는 문자열 검색, 추출, 치환

ex. 151-878
/\d{3}-\d{3} /

JS의 정규 표현식 : RegExp 객체

const reg = new RegExp("abc"); 	// RegExp 생성자 : 패턴을 인수로 넘김
const reg = /abc/; 		// 정규 표현식 리터럴 : 패턴을 슬래시로 묶음
=> "abc" 라는 문자열을 포함한다.

RegExp 객체의 메서드

JS로 정규 표현식을 사용해 문자열을 처리하려면

  • RegExp.prototype 의 test, exec 메서드
  • String.prototype 의 match, replace, search, split 메서드 ➡ 12.3

test 메서드 : 일치하는지 논리값을 반환
문자열이 정규 표현식의 패턴을 갖는지 확인 : 패턴 매칭

const reg = /cat/;
reg.test("cat"); 		// true
reg.test("ca"); 		// false
reg.test("Cat"); 		// false
reg.test("cats and dogs"); 	// true
reg.test("locate"); 		// true

exec 메서드 : 일치하는 문자열을 배열로 반환 (없으면 null)
반환된 배열의 프로퍼티 index, input

const reg = /Script/;
const resultArray = reg.exec("JavaScript");
resultArray; 			// ["Script"]
resultArray[0]; 		// Script

resultArray.index; 		// 4 : 처음 일치한 위치
resultArray.input; 		// JavaScript : 일치한 문자열

일반문자 (리터럴문자)

숫자(0~9), 알파벳(a~z, A~Z) 등
✨ 앞에 \ 역슬래시가 붙은 리터럴문자는 문자로 표기할수 없는 특수문자

유니코드 문자		문자 자체 (메타문자 제외)
\0			NULL (\u0000)
\n			개행 (LF=\u000A)
\t			탭 (\u0009)
\v			수직 탭 (\u000B)
\f			다음 페이지 (FF=\u000C)
\r			캐리지 리턴 (CR=\u000D)
\xhh			16진수 hh로 지정된 ASCII
\uhhhh			16진수 hhhh로 지정된 유니코드
\cX			제어 문자

특수문자 (의미를 갖는 메타문자)

✨ 메타문자를 문자로서 표기할때는 앞에 \ 역슬래시를 붙여 이스케이프

^ $ \ . * + ? ( ) [ ] { } |

문자 클래스 안에서 사용하면 문자 자체를 의미 !

문자 클래스

[...] : 문자 클래스

● 대괄호 안에 집합의 요소가 되는 문자 리터럴을 나열
[abc] 			// 'a','b','c' 중 1개라도 일치
[0123456789]		// 숫자 1개라도 일치

/[0123456789]/.test("10days"); 	// true

● 대괄호 안에서 하이픈(-)을 사용해 문자의 범위 지정
[a-z] 			// 소문자 1개
[abcx-z]		// a,b,c,x,y,z 중 1개
[a-zA-Z0-9]		// 모든 알파벳, 숫자 중 1개
[\u3131-\u314E]		// 한글 자음 1개

/[\u3131-\u314E]/.test("ㄱ"); 	// true

[^...] : 부정 문자 클래스

/[^0-9]/.test("137");		// false

문자 클래스의 단축 표기

. 	: 임의의 문자 1개 (줄바꿈 문자 제외)
/c..l/	// "hot and cool" (O), "console" (X)

\d, \D	: 숫자(digit)와 그 외의 문자
const datetime = /\d\d\d\d-\d\d-\d\d \d\d:\d\d/;
datetime.test("it's 2020-08-27 10:15"); // true
\D === [^0123456789] 👀

\w, \W	: 영어 단어 문자(word character, 알파벳·숫자·언더바)와 그 외의 문자
\w === [a-zA-Z0-9_] 👀
/\w/.test("A");		// true
/\w/.test("!@");	// false
/\w/.test("A!");	// true
/\W/.test("A!");	// true

\s, \S	: 공백 문자(space, 공백·탭·개행)와 그 외의 문자
/\s\w\w/.exec("JavaScript RegExp");	// [" Re"]

\d, \D, \w, \W, \s, \S 는 [문자 클래스] 안에서도 사용 가능!

반복 패턴

반복을 지정하는 문자열

  • {m,n} : 최소 m번, 최대 n번 반복
/[a-z]{6,12}/ 		: 알파벳 소문자가 6자 이상 12자 이하인 문자열
  • {n,} : 최소 n번 이상 반복
/[a-z]{6,}/		: 알파벳 소문자가 6자 이상인 문자열
  • {n} : n번 반복 ( {n,n} )
/[a-z]{4}\d{3}/		: 알파벳 소문자가 4자, 그 뒤에 숫자가 3자

const datetime = /\d{4}-\d{2}-\d{2} \d{2}:\d{2}/;
datetime.test("it's 2020-08-27 10:15"); // true
  • ? : 최소 0번, 최대 1번 반복 ( {0,1} )
/[a-z]{4}\d?/		: 알파벳 소문자가 4자, 그 뒤에 숫자가 없거나 1개
  • + : 최소 1번 이상 반복 ( {1,} )
/\s+Tom\s+/		: Tom 앞뒤에 공백 문자가 최소 1자 이상
/\s+Tom\s+/.test(" Tom "); // true
  • * : 최소 0번 이상 반복 ( {0,} )
/[a-z]{4}\d*/		: 알파벳 소문자가 4자, 그 다음 숫자가 0개 이상

/[a-z]{4}\d*/.exec("kim");	// null
/[a-z]{4}\d*/.exec("park");	// ["park"]
/[a-z]{4}/.exec("park"); 	// ["park"]

/[a-z]{4}\d*/.exec("park1234");	// ["park1234"]
/[a-z]{4}/.exec("park1234");	// ["park"]

욕심👼🏻

* : 최대한 반복 ✔ 욕심 많은 반복
반복 문자 뒤에 ? : 최소한으로 반복 ✔ 욕심 없는 반복

/Java.?/.exec("I love JavaScript really"); 	// ["JavaS"]
/Java.??/.exec("I love JavaScript really"); 	// ["Java"]

/Java.+/.exec("I love JavaScript really");	// ["JavaScript really"]
/Java.+?/.exec("I love JavaScript really");	// ["JavaS"]

/Java.*/.exec("I love JavaScript really"); 	// ["JavaScript really"]
/Java.*?/.exec("I love JavaScript really"); 	// ["Java"]

그룹화

정규 표현식의 패턴 요소를 소괄호로 묶어서 부분적으로 그룹화 : 부분 정규 표현식
부분 정규 표현식과 일치한 값을 저장 : 캡쳐링(저장)

const header = /<h[1-6].*<\/h[1-6]>/;
header.test("<h1>정규화 어렵다</h1>"); 	// true
header.test("<h1>정규화 어렵다</h2>"); 	// true

const header = /<(h[1-6]).*<\/\1>/;
header.test("<h1>정규화 어렵다</h2>"); 	// false
header.test("<h1>정규화 어렵다</h1>"); 	// true

\1 은 1번째 부분 정규 표현식을 참조
\n 은 n번째 부분 정규 표현식을 참조

exec 메서드가 반환하는 배열의 1번째 요소에는 정규 표현식과 일치한 마지막 문자열,
그 이후의 요소에는 부분 정규 표현식과 일치한 문자열
(?: ...) : 캡쳐링 없는 그룹화

const header = /<(h[1-6]).*<\/\1>/;
header.exec("<h1>정규화 어렵다</h1>"); 	// ["<h1>정규화 어렵다</h1>", "h1"]

const header = /<(?:h[1-6]).*<\/\1>/;
header.exec("<h1>정규화 어렵다</h1>");	// null

const header = /<(?:h[1-6]).*<\/h[1-6]>/;
header.exec("<h1>정규화 어렵다</h1>"); 	// ["<h1>정규화 어렵다</h1>"]


const postalCode = /(?:\d{3})-(?:\d{3})/;
postalCode.test("463-803");	// true
postalCode.exec("463-803");	// ["463-803"]

const postalCode = /(\d{3})-\d{3}/;
postalCode.exec("463-803"); 	// ["463-803", "463"]

앵커

문자열의 위치를 패턴으로 지정

^ : 문자열의 시작

const str = /^정규화/;
str.test("정규화 어렵다");	// true
str.test("어려운 정규화");	// false

🚨 문자 클래스 ( [^...] ) 	부정 (not)
🚨 여러줄 모드 ( /.../m ) 	행의 시작

$ : 문자열의 끝

const str = /정규화$/;
str.test("정규화 어렵다");	// false
str.test("어려운 정규화");	// true

🚨 여러줄 모드 ( /.../m ) 	행의 끝

^ ... $

const str = /^정규화$/;
str.test("정규화 어렵다");	// false
str.test("어려운 정규화");	// false
str.test("정규화");		// true

\b, \B : 영어 단어 경계(boundary)와 그 외의 위치

/\bdog\b/.test("dog"); 		// true
/\bdog/.test("dogdogdog");	// "dog"dogdog
/\bdog\b/.test("dogdogdog");	// false
/\bdog\B/.test("dogdogdog"); 	// "dog"dogdog
/\Bdog\B/.test("dogdogdog"); 	// dog"dog"dog

x(?=y) : 전방 탐색 x 다음에 y

/롯데(?=시네마)/.exec("롯데시네마"); 	// ["롯데"]
/롯데(?=시네마)/.exec("롯데백화점"); 	// null

x(?!y) : 전방 부정 탐색 x 다음에 y 가 아닌것

/롯데(?!시네마)/.exec("롯데시네마"); 	// null
/롯데(?!시네마)/.exec("롯데백화점"); 	// ["롯데"]
/롯데(?!시네마)/.exec("롯데월드"); 	// ["롯데"]

선택 패턴 | (OR)

후보가 되는 여러 문자열

const countFruits = /\b(\d+) (apple|peach|orange)s?\b/;

const result = countFruits.exec("10 apples");
result		// ["10 apples", "10", "apple"]
result[1]	// 10

const result = countFruits.test("an apple"); 	// false
const result = countFruits.test("10 peaches"); 	// false
const result = countFruits.test("10apples");	// false

플래그

i, g, m, y, u

i	case-insensitive 대소문자 구별없이
g	global 일치하는 모든 문자열
m 	multiple line 여러줄 모드


const reg = new RegExp("abc","g");
const reg = /abc/gi;

const multipleLine = "Dog\nCat\nMonkey";
/^cat/im.test(multipleLine);	// true
/cat$/im.test(multipleLine);	// true

const multipleLine = "Dog Cat Monkey";
/^cat/im.test(multipleLine);	// false
/cat$/im.test(multipleLine);	// false

철도 다이어그램
https://regexper.com/

참고자료
https://regex101.com/
https://velog.io/@koseungbin/정규-표현식
https://ko.wikipedia.org/wiki/정규_표현식
https://opentutorials.org/course/50/43
https://opentutorials.org/course/909/5143
http://zvon.org/comp/m/regexp.html
http://coffeenix.net/doc/misc/regex.html

0개의 댓글