C# 정규 표현식 수량자란?
수량자(Quantifier)는 정규 표현식에서 바로 앞의 요소(문자, 그룹 또는 문자 클래스)가 입력 문자열 안에서 몇 번 나타나야 일치(match)로 간주되는지를 지정하는 특수 문자입니다. 즉, 반복 횟수를 제어하는 역할을 하며, 정규식 패턴 작성 시 가장 자주 사용되는 핵심 요소 중 하나입니다.
예를 들어 * 수량자는 앞의 요소가 0번 이상 반복될 때 일치하므로, \d*\.\d 같은 패턴은 ".0", "19.9", "219.9" 등 다양한 소수 형태의 문자열과 매칭할 수 있습니다.
C#에서 사용할 수 있는 모든 수량자
아래 표는 C# 정규 표현식(.NET Regex)에서 사용할 수 있는 수량자 전체 목록입니다.
| 수량자 | 설명 | 패턴 | 일치 결과 |
|---|---|---|---|
| * | 이전 요소와 0번 이상 일치합니다. | \d*\.\d | ".0", "19.9", "219.9" |
| + | 이전 요소와 1번 이상 일치합니다. | "be+" | "been"의 "bee", "bent"의 "be" |
| ? | 이전 요소와 0번 또는 1번 일치합니다. | "rai?n" | "ran", "rain" |
| { n } | 이전 요소와 정확히 n번 일치합니다. | ",\d{3}" | "1,043.6"의 ",043", "9,876,543,210"의 ",876", ",543", ",210" |
| { n } | 이전 요소와 최소 n번 일치합니다. | "\d{2}" | "166", "29", "1930" |
| { n , m } | 이전 요소와 최소 n번, 최대 m번 일치합니다. | "\d{3,5}" | "166", "17668", "193024"의 "19302" |
| *? | 이전 요소와 0번 이상 일치하지만, 가능한 한 가장 적은 횟수로 일치합니다. | \d*?\.\d | ".0", "19.9", "219.9" |
| +? | 이전 요소와 1번 이상 일치하지만, 가능한 한 가장 적은 횟수로 일치합니다. | "be+?" | "been"의 "be", "bent"의 "be" |
| ?? | 이전 요소와 0번 또는 1번 일치하지만, 가능한 한 가장 적은 횟수로 일치합니다. | "rai??n" | "ran", "rain" |
| { n }? | 이전 요소와 정확히 n번 일치합니다. | ",\d{3}?" | "1,043.6"의 ",043", "9,876,543,210"의 ",876", ",543", ",210" |
| { n }? | 이전 요소와 최소 n번 일치하지만, 가능한 한 가장 적은 횟수로 일치합니다. | "\d{2}?" | "166", "29", "1930" |
| { n , m }? | 이전 요소와 n번 이상 m번 이하로 일치하지만, 가능한 한 가장 적은 횟수로 일치합니다. | "\d{3,5}?" | "166", "17668", "193024"의 "193", "024" |
탐욕적(Greedy) 수량자 vs 게으른(Lazy) 수량자
위 표에서 눈여겨볼 점은 수량자 뒤에 물음표(?)를 붙인 형태들입니다. 기본 수량자(*, +, {n,m} 등)는 탐욕적(greedy)으로 동작하여 가능한 한 많은 문자를 소비하려 하지만, 뒤에 ?를 붙이면 게으른(lazy) 방식으로 바뀌어 가능한 한 적은 문자만 소비하고 일치를 종료합니다.
예를 들어 \d{3,5} 패턴은 "193024"라는 문자열에서 최대한 많이 먹어 "19302"를 반환하지만, \d{3,5}? 패턴은 최소 조건인 3자리만 만족하면 바로 멈추기 때문에 "193"과 "024"로 나누어 일치시킵니다. 이 차이를 이해하면 HTML 태그 추출, 로그 파싱 등 실무 정규식 작성 시 원하지 않는 과다 매칭 문제를 쉽게 해결할 수 있습니다.
마무리
C#의 System.Text.RegularExpressions.Regex 클래스와 함께 위 수량자들을 활용하면 숫자, 구분 기호, 반복 패턴 등을 유연하게 검색하고 추출할 수 있습니다. 처음에는 *, +, ? 세 가지 기본 수량자부터 익히고, 이후 범위 지정({n,m})과 게으른 매칭(*?, +?)으로 확장해 나가는 것을 추천합니다.