[기본 개념] 정규 표현식
1> 정규 표현식 구성
2> 정규식 메서드
3> 정규식 플래그
4> 정규식 기호모음
5> 정규식 그룹화
6> 정규 표현식 테스트 사이트
1 정규 표현식 구성
슬래쉬 문자 두 개 사이로 정규식 기호가 들어가는 형태이다.
2 정규식 메서드
메서드 | 설명 |
("문자열").match(/정규표현식/플래그) | "문자열"에서 "정규표현식"에 매칭되는 항목들을 배열로 반환 |
("문자열").replace(/정규표현식/, "대체문자열") | "정규표현식"에 매칭되는 항목을 "대체문자열"로 변환 |
("문자열").split(정규표현식) | "문자열"을 "정규표현식"에 매칭되는 항목으로 쪼개어 배열로 반환 |
(정규표현식).test("문자열") | "문자열"이 "정규표현식"과 매칭되면 true, 아니면 false 반환 |
(정규표현식).exec("문자열") | match 메서드와 유사(단, 무조건 첫번째 매칭 결과만 반환) |
3 정규식 플래그
정규식 플래그는 정규식을 생성할 때 고급 검색을 위한 전역 옵션을 설정할 수 있도록 지원하는 기능이다.
플래그 | 의미 | 설명 |
i | Insensitive | 대소문자를 구별하지 않고 검색 |
g | Global | 문자열 내의 모든 패턴을 검색 |
m | Multi Line | 문자열의 행이 바뀌더라도 검색을 계속 |
s | single line | .(모든 문자 정규식)이 개행 문자 \n도 포함하도록 `a1.a2\na3`.replace(/./g, 'z') 결과: "zzzzz\nzz" `a1.a2\na3`.replace(/./gs, 'z') 결과: "zzzzzzzz" |
u | unicode | 패턴을 유니코드 코드 포인트의 나열로 취급 `a1a2a3`.replace(/\p{N}/g, 'z') 결과: "a1a2a3" `a1a2a3`.replace(/\p{N}/gu, 'z') 결과: "azazaz" (\p{...} 유니코드 범주 사용) |
y | sticky | 문자열의 현재 위치부터 검색 ‘sticky’ 모드를 활성화 const str = 'aaabb'; const regex = /a/y; regex.test(str); //true < aaabb 찾음 regex.test(str); //false < 찍고 초기화 regex.test(str); //true < aaabb 찾음 regex.test(str); //true < aaabb 찾음 regex.test(str); //true < aaabb 찾음 regex.test(str); //false < aaabb 찍고 초기화 |
g 플래그 : 전역 검색
g 플래그가 없는 경우 : 최초 검색 결과 1번만 반환
g 플래그가 있는 경우 : 모든 결과 배열로 반환
// `a`가 두 개 포함된 문자열
const str = "abcabc";
// `g` 플래그 없이는 최초에 발견된 문자만 반환
str.match(/a/); // ["a", index: 0, input: "abcabc", groups: undefined]
// `g` 플래그가 있으면 모든 결과가 배열로 반환
str.match(/a/g); // (2) ["a", "a"]
m 플래그 : 줄 바뀜 검색
여러 줄의 문자열에서 필터링해야 할 때 사용한다.
입력 시작(^) 앵커나 입력 종료($) 앵커는 전체 문자열이 아닌 각 줄 별로 대응되게 만들어졌기 때문에 여러 줄을 검색해야 한다면 사용한다.
// 줄바꿈이 포함된 3줄 문자열
const str = "Hello World and\nPower Hello?\nPower Overwhelming!!";
/*
Hello World and
Power Hello?
Power Overwhelming!!
*/
// Hello 단어로 시작하는지 검사 (^ : 문장 시작점을 의미)
str.match(/^Hello/); // ["Hello"]
// → 첫번째 줄은 잘 찾음
// Power 단어로 시작하는지 검사 (^ : 문장 시작점을 의미)
str.match(/^Power/); // null
// 따라서 m 플래그를 통해 개행되는 다음 줄도 검색되게 설정
str.match(/^Power/m); // ['Power']
// 세번째 줄도 검색되게 하고싶으면 g 플래그와 혼합 사용
str.match(/^Power/gm); // ['Power', 'Power']
4 정규식 기호 모음
정규식 특정 문자 숫자 매칭 패턴
패턴 | 설명 |
a-zA-Z | 영어 알파벳 (- 으로 범위 지정) |
ㄱ-ㅎ가-힣 | 한글 문자 (- 으로 범위 지정) |
0-9 | 숫자 (- 으로 범위 지정) |
. | 모든 문자열 (숫자, 한글, 영어, 특수기호, 공백 모두) 줄바꿈 X |
\d | 숫자 |
\D | 숫자가 아닌 것 |
\w | 밑줄 문자(_)를 포함한 영 숫자 문자에 대응 [A-Za-z0-9_] 와 동일 |
\W | \w 가 아닌 것 |
\s | space 공백 |
\S | space 공백이 아닌 것 |
\특수기호 | 특수기호 \* \^ \& \! \? ...등 |
\b | 63개 문자(영문 대소문자 52개 + 숫자 10개 + 밑줄 문자(_))가 아닌 나머지 문자에 일치하는 경계 (boundary) |
\B | 63개 문자에 일치하는 경계 |
\x | 16진수 문자에 일치 /\x61/는 a에 일치 |
\0 | 8진수 문자에 일치 /\141/은 a에 일치 |
\u | 유니코드 (Unicode) 문자에 일치 /\u0061/는 a에 일치 |
\c | 제어 (Control) 문자에 일치 |
\f | 폼 피드 (FF, U+000C) 문자에 일치 |
\n | 줄 바꿈 (LF, U+000A) 문자에 일치 |
\r | 캐리지 리턴 (CR, U+000D) 문자에 일치 |
정규식 검색 기준 패턴
기호 | 설명 |
| | OR a|b |
[] | 괄호안의 문자들 중 하나. or 처리 묶음 보면 된다. /abc/ : "abc"를 포함하는 /[abc]/ : "a" 또는 "b" 또는 "c" 를 포함하는 [다-바] : 다 or 라 or 마 or 바 |
[^문자] | 괄호안의 문자를 제외한 것 /[^abc]/ a b c 3개 문자를 제외, /[^a-c]/ 와 같은 의미 "brisket"의 'r', "chop."의 'h'에 대응 (g 플래그가 아님) (대괄호 안에서 쓰면 제외의 뜻, 대괄호 밖에서 쓰면 시작점 뜻) |
^문자열 | 특정 문자열로 시작 (시작점) /^www/ |
문자열$ | 특정 문자열로 끝남 (종착점) /com$/ |
정규식 개수 반복 패턴
기호 | 설명 |
? | 0회나 1회이상 연속으로 반복 /e?le?/ => el, ele, le, l 에 대응 *, +, ?, {} 뒤에 사용하면, 가능한 많이 대응시킨 수량자를 가능한 가장 적은 문자들에 대응시킴 "123abc" /\d+/ => 123 /\d+?/ => 1 (g 플래그있으면 1, 2, 3) |
* | 0회 이상 연속으로 반복, {0,} 와 같은 의미 /apple*/ => appl 에 대응 |
+ | 1회 이상 연속으로 반복, {1,} 와 같은 의미 /apple+/ => apple, appleee 등 에 대응 |
*? | 없거나, 있거나 and 없거나, 최대 한 개 : 없음 {0} 와 동일 |
+? | 최소 한 개, 있거나 and 없거나, 최대 한 개 : 한 개 {1} 와 동일 |
{n} | n 개 |
{Min,} | 최소 Min 개 이상 |
{Min, Max} | 최소 Min 개 이상, 최대 Max 개 이하 {3,5}? == {3} 와 동일 |
정규식 그룹 패턴
기호 | 설명 |
() | 그룹화 및 캡쳐 |
(?: 패턴) | 그룹화 (캡쳐 X) |
(?=) | 앞쪽 일치 (Lookahead) /ab(?=c)/ => c 가 뒤따라오는 ab 에만 대응 |
(?!) | 부정 앞쪽 일치 (Negative Lookahead) /ab(?!c)/ => c 가 뒤따라오지 않는 ab 에만 대응 "3.141" /\d+(?!\.)/ => 141 에 대응 |
(?<=) | 뒤쪽 일치 (Lookbehind) /(?<=ab)c/ => ab 가 앞에 있는 c 에만 대응 |
(?<!) | 부정 뒤쪽 일치(Negative Lookbehind) /(?<!ab)c/ => ab 가 앞에 없는 c 에만 대응 |
5 정규식 그룹화
'kokokoko'.match(/ko+/); // "ko"
'kooookoooo'.match(/ko+/); // "koooo"
표현식 "ko+" 은 "o" 만 + 를 적용시켜 ("k" 는 적용 X)
=> "koooo" 가 반환되었다.
'kokokoko'.match(/(ko)+/); // "kokokoko", "ko"
'kooookoooo'.match(/(ko)+/); // "ko", "ko"
하지만 표현식 "(ko)+" 는 "k" 와 "o" 를 묶었기 (그룹화) 때문에 "ko" 자체를 1회 이상 연속으로 반복
=> "kokokoko" 가 반환되었다.
그런데 패턴 ( ) 를 사용한 정규식들의 결과는 2개가 나온다. 플래그 g 를 사용하지 않고, 한 번만 사용했는데 2개가 나온 이유는 캡처 기능 때문이다.
정규식 캡쳐 기능
패턴 그룹화 ( ) 는 괄호 안의 표현식을 캡처하여 사용한다.
'kokokoko'.match(/(ko)+/); // "kokokoko", "ko"
1. 패턴 ( ) 안에 있는 "ko" 를 그룹화하여 캡처
2. 그룹화된 "ko" 를 패턴 + 로 1회 이상 반복되는 문자로 검색
("kokokoko" 반환)
3. 캡처 외 표현식이 모두 작동하고 난 뒤, 캡처된 표현식 "ko" 가 검색
("ko" 반환)
'123abc'.match(/(\d+)(\w)/); // "123a", "123", "a"
1. 패턴 ( ) 안에 있는 "\d+", "\w" 를 그룹화하여 캡처
2. 캡처 후 남는 표현식으로 검색
3. 그룹화된 "\d" 를 패턴 + 로 1회 이상 연속되는 숫자를 검색 "123" 일치
4. 다음 패턴 "\w" 는 문자를 검색하니 "a"가 일치
("123a" 반환)
5. 첫 번째 캡처한 표현식 "\d+" 로 숫자를 재검색하되, 패턴 + 로 1회 이상 연속되는 숫자를 검색 "123" 일치
("123" 반환)
6. 나머지 캡쳐한 표현식 "\w" 로 문자를 재검색하니, "a" 일치
("a" 반환)
캡처하지 않는 그룹화 ?:
뜻하지 않은 정규식 그룹화 캡처 기능이 싫다면 괄호 안 ?: 문자를 통해 캡처를 비활성화 할 수 있다.
// 그룹화 + 캡처
'kokokoko'.match(/(ko)+/); // "kokokoko", "ko"
// 그룹화만
'kokokoko'.match(/(?:ko)+/); // "kokokoko"
표현식 캡쳐를 하지 않기 때문에 "k" 와 "o" 를 그룹화 한 "ko" 만으로 검색되게 된다.
6 정규 표현식 테스트 사이트