패턴의 반복과 그룹화
1. 수량자
수량자는 앞의 패턴이 몇 번 반복되는지를 지정하는 특수 문자입니다. 수량자를 사용하면 반복되는 패턴을 간단하게 표현할 수 있습니다.
1.1 기본 수량자
기본 수량자는 패턴의 반복 횟수를 간단히 표현할 수 있습니다.
| 수량자 | 의미 | 동등 표현 |
|---|---|---|
* | 0회 이상 반복 | {0,} |
+ | 1회 이상 반복 | {1,} |
? | 0회 또는 1회 (선택적) | {0,1} |
/a*/ // a가 0회 이상 반복
/a+/ // a가 1회 이상 반복
/a?/ // a가 0회 또는 1회 (있거나 없거나)
예시를 통해 각각의 차이를 자세히 살펴보겠습니다.
*: 0회 이상
/ho*/gm
// "h" 매칭됨 (o가 0회)
// "ho" 매칭됨 (o가 1회)
// "hoo" 매칭됨 (o가 2회)
// "hooo" 매칭됨 (o가 3회)
+: 1회 이상
/ho+/gm
// "h" 매칭 안됨
// "ho" 매칭됨 (o가 1회)
// "hoo" 매칭됨 (o가 2회)
// "hooo" 매칭됨 (o가 3회)
?: 0회 또는 1회
/ho?/gm
// "h" 매칭됨 (o가 0회)
// "ho" 매칭됨 (o가 1회)
// "hoo"에서 "ho"만 매칭 (두 번째 o는 매칭 안됨)
아래와 같이 활용 될 수 있습니다.
/https?/gm // http 또는 https 매칭
/\d+/gm // 하나 이상의 숫자 매칭
/\w*/gm // 단어 문자가 0개 이상 매칭
1.2 중괄호 수량자
중괄호를 사용하면 반복 횟수를 더 정확하게 지정할 수 있습니다.
/a{3}/ // a가 정확히 3회 반복
/a{3,}/ // a가 3회 이상 반복
/a{3,5}/ // a가 3회 이상 5회 이하 반복
아래와 같이 활용될 수 있습니다.
// 휴대폰 번호 패턴
/\d{3}-\d{4}-\d{4}/gm // 010-1234-5678
// 2~3자리 국가 코드
/[A-Z]{2,3}/gm // US, KR, USA
// 3글자 이상의 단어
/[A-Za-z]{3,}/gm // cat(X), apple(O), banana(O)
// 2자리 연도
/\d{2}년/gm // 98년, 24년
// 우편번호
/\d{5}/gm // 12345
앞에 기본 수량자를 중괄호 수량자로 바꾸면 아래와 같아집니다.
| 기본 수량자 | 중괄호 수량자 | 설명 |
|---|---|---|
* | {0,} | 0개 이상 |
+ | {1,} | 1개 이상 |
? | {0,1} | 0개 또는 1개 |
중괄호 사용 시 주의사항
- 중괄호 안에 공백이 있으면 안됩니다:
/\d{3, 4}/(X) →/\d{3,4}/(O) - 콤마 뒤의 숫자를 생략하면 무한대를 의미합니다:
/\d{3,}/ - 범위의 시작 숫자는 끝 숫자보다 작아야 합니다
1.3 탐욕적 vs 비탐욕적 매칭
기본적으로 수량자는 탐욕적(Greedy)으로 동작합니다. 즉, 가능한 많은 문자를 매칭하려고 합니다. 수량자 뒤에 ?를 붙이면 비탐욕적(Lazy) 매칭이 됩니다.
// 탐욕적 매칭 (기본)
/<.*>/gm // <div>hello</div>에서 "<div>hello</div>" 전체 매칭
// 비탐욕적 매칭
/<.*?>/gm // <div>hello</div>에서 "<div>"만 매칭
| 탐욕적 | 비탐욕적 | 설명 |
|---|---|---|
* | *? | 가능한 적게 매칭 (0회부터) |
+ | +? | 가능한 적게 매칭 (1회부터) |
? | ?? | 가능한 적게 매칭 (0회 우선) |
{n,m} | {n,m}? | 가능한 적게 매칭 (n회부터) |
HTML 태그 등을 추출할 때는 비탐욕적 매칭을 사용하면 각 태그를 개별적으로 매칭할 수 있습니다.
2. 그룹화와 캡처
2.1 OR 연산자
파이프(|) 기호를 사용하여 여러 패턴 중 하나를 선택할 수 있습니다.
/cat|dog/gm // cat 또는 dog
/hello|hi|hey/gm // hello, hi, hey 중 하나
2.2 기본 그룹화
소괄호를 사용하여 패턴을 그룹화할 수 있습니다. 그룹화를 통해 여러 문자를 하나의 단위로 취급할 수 있습니다.
/(hello)+/ // hello가 1회 이상 반복
/(hello|world)/ // hello 또는 world
/h(e|a)llo/ // hello 또는 hallo
아래와 같이 활용될 수 있습니다.
// 파일 확장자
/\.(jpg|jpeg|png|gif)$/gm
// 요일
/(월|화|수|목|금|토|일)요일/gm
// 특정 도메인
/@(gmail|naver|kakao)\./gm
// 반복되는 단어
/(hello){2}/gm // hellohello
// 도메인 패턴
/(com|net|org)/gm // example.com, example.net, example.org
// 이름 패턴
/(김|이|박)씨/gm // 김씨, 이씨, 박씨
// 날짜 형식
/(연도|월|일)/gm // 2024연도, 11월, 2일
2.3 캡처 그룹
그룹화한 패턴을 나중에 참조할 수 있습니다. 이를 후방 참조(Backreference)라고 합니다. 캡처된 그룹은 \1, \2 등으로 참조할 수 있으며, 숫자는 그룹의 순서를 나타냅니다.
/(hello) \1/ // hello hello (같은 단어 반복)
/(\d+) \1/ // 숫자가 공백을 두고 반복: "123 123"
/(\d+)-\1/ // 숫자가 대시를 두고 반복: "123-123"
아래와 같이 활용할 수 있습니다.
// 반복된 단어 찾기
/(\b\w+\b) \1/gm
// "the the" 매칭됨
// "hello hello" 매칭됨
// "hello world" 매칭 안됨
// HTML 태그 매칭
/<(\w+)>.*?<\/\1>/gm
// "<div>내용</div>" 매칭됨
// "<p>문단</p>" 매칭됨
// 중복된 숫자 패턴
/(\d)\1+/gm
// "111" 매칭됨
// "222" 매칭됨
// "123" 매칭 안됨
3. 연습 예제
3.1 문제
- 전화번호 형식(010-1234-5678)을 찾는 패턴을 만드세요.
- 같은 단어가 연속해서 나오는 경우를 찾는 패턴을 만드세요.
- http 또는 https로 시작하는 URL을 찾는 패턴을 만드세요.
- 세 글자 이상의 단어를 찾는 패턴을 만드세요.
- 같은 숫자가 2번 이상 반복되는 패턴을 찾으세요.
- 이메일 주소에서 도메인 부분만 찾는 패턴을 만드세요.
- HTML 태그 쌍을 찾는 패턴을 만드세요.
- 연속된 세 글자 이상의 알파벳을 찾는 패턴을 만드세요.
3.2 해답
/\d{3}-\d{4}-\d{4}/gm/(\w+) \1/gm/https?:\/\//gm/[a-zA-Z]{3,}/gm/(\d)\1+/gm/@([a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)/gm/<(\w+)>.*?<\/\1>/gm/[a-zA-Z]{3,}/gm