본문 바로가기

패턴의 반복과 그룹화

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개

중괄호 사용 시 주의사항

  1. 중괄호 안에 공백이 있으면 안됩니다: /\d{3, 4}/ (X) → /\d{3,4}/ (O)
  2. 콤마 뒤의 숫자를 생략하면 무한대를 의미합니다: /\d{3,}/
  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 문제

  1. 전화번호 형식(010-1234-5678)을 찾는 패턴을 만드세요.
  2. 같은 단어가 연속해서 나오는 경우를 찾는 패턴을 만드세요.
  3. http 또는 https로 시작하는 URL을 찾는 패턴을 만드세요.
  4. 세 글자 이상의 단어를 찾는 패턴을 만드세요.
  5. 같은 숫자가 2번 이상 반복되는 패턴을 찾으세요.
  6. 이메일 주소에서 도메인 부분만 찾는 패턴을 만드세요.
  7. HTML 태그 쌍을 찾는 패턴을 만드세요.
  8. 연속된 세 글자 이상의 알파벳을 찾는 패턴을 만드세요.

3.2 해답

  1. /\d{3}-\d{4}-\d{4}/gm
  2. /(\w+) \1/gm
  3. /https?:\/\//gm
  4. /[a-zA-Z]{3,}/gm
  5. /(\d)\1+/gm
  6. /@([a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)/gm
  7. /<(\w+)>.*?<\/\1>/gm
  8. /[a-zA-Z]{3,}/gm