re_syntax — Tcl 정규 표현식의 문법

re_syntax — Tcl 정규 표현식의 문법

정규 표현식(regex)은 문자열을 기술하는 방법이에요. 어떤 문자열들과는 일치하고 어떤 것과는 일치하지 않는 패턴인 셈이죠. Tcl에서 regexp, regsub, switch, lsearch 등 여러 명령이 내부적으로 이 정규식을 사용해요. 이 페이지는 그 정규식의 문법을 자세히 다루는 참조 문서예요.

출처: 문서

본문

정규식의 세 가지 계열(FLAVORS)

POSIX가 정의한 정규식("RE")에는 두 가지 계열이 있어요: 확장 정규식("ERE")과 기본 정규식("BRE")이에요. ERE는 대략 전통적인 egrep의 것, BRE는 대략 전통적인 ed의 것이라고 보면 돼요. 이 구현은 여기에 세 번째 계열인 고급 정규식("ARE")을 더하는데, 기본적으로 의미 있는 확장을 몇 가지 추가한 ERE라고 할 수 있어요.

이 매뉴얼 페이지는 주로 ARE를 설명해요. BRE는 일부 옛 프로그램의 하위 호환성을 위해 주로 존재하며, 마지막에 논의돼요. POSIX ERE는 ARE의 거의 정확한 부분집합이에요. ERE에 없는 ARE의 기능은 따로 표시해요.

정규식 문법 구조

Tcl 정규식은 Henry Spencer가 작성한 패키지로 구현되는데, 1003.2 스펙과 Perl5 확장의 일부(전부는 아님)를 기반으로 해요.

ARE는 |로 구분된 하나 이상의 브랜치(branch)로 구성돼요. 브랜치 중 어느 하나와 일치하면 전체가 일치하는 거죠.

브랜치는 0개 이상의 제약(constraint) 또는 양화 원자(quantified atom)가 이어 붙은 것이에요. 첫 번째 일치 다음에 두 번째 일치가 오는 식으로 순서대로 일치해요. 빈 브랜치는 빈 문자열과 일치해요.

양화자(QUANTIFIERS)

양화 원자는 원자 뒤에 단일 양화자가 올 수 있는 형태예요. 양화자가 없으면 원자의 단일 매치와 일치해요. 양화자와 그 의미는 다음과 같아요:

  • * — 원자의 0개 이상 매치 시퀀스
  • + — 원자의 1개 이상 매치 시퀀스
  • ? — 원자의 0개 또는 1개 매치 시퀀스
  • {m} — 정확히 m개의 매치 시퀀스
  • {m,} — m개 이상의 매치 시퀀스
  • {m,n} — m개부터 n개(포함)까지의 매치 시퀀스; m은 n을 초과할 수 없음
  • *? +? ?? {m}? {m,}? {m,n}? — 비탐욕적(greedy하지 않은) 양화자로, 같은 가능성을 매치하지만 최대가 아닌 최소 매치 수를 선호해요

{}를 쓰는 형태를 바운드(bounds)라고 불러요. 숫자 m과 n은 부호 없는 십진 정수로, 0부터 255까지의 값을 가질 수 있어요.

원자(ATOMS)

원자는 다음 중 하나예요:

  • (re) — re(임의의 정규식)의 매치와 일치하되, 그 매치를 보고용으로 기록
  • (?:re) — 위와 같지만 보고하지 않음("비캡처" 괄호)
  • () — 빈 문자열과 일치, 보고용으로 기록
  • (?:) — 보고 없이 빈 문자열과 일치
  • [chars] — 대괄호 표현식, chars 중 하나와 일치
  • . — 임의의 단일 문자와 일치
  • \k — 비알파벳숫자 문자 k를 일반 문자로 취급, 예: \\는 백슬래시 문자
  • \c — c가 알파벳숫자일 때(뒤에 다른 문자가 올 수도), 이스케이프(ARE 전용)
  • { — 숫자가 아닌 문자가 뒤에 오면 좌중괄호 문자 {와 일치; 숫자가 뒤에 오면 바운드의 시작
  • x — 다른 의미가 없는 단일 문자 x, 그 문자 그대로와 일치

제약(CONSTRAINTS)

제약은 특정 조건이 충족될 때 빈 문자열과 일치해요. 제약 뒤에는 양화자가 올 수 없어요. 기본적인 제약은 다음과 같아요:

  • ^ — 문자열 또는 줄의 시작에서 일치 (매칭이 개행 민감인지에 따라 다름)
  • $ — 문자열 또는 줄의 끝에서 일치
  • (?=re) — positive lookahead(ARE 전용), re와 일치하는 부분 문자열이 시작되는 지점에서 일치
  • (?!re) — negative lookahead(ARE 전용), re와 일치하는 부분 문자열이 시작되지 않는 지점에서 일치

\A\Z 제약 이스케이프는 비슷한 목적이지만 항상 전체 문자열에 대한 제약이에요. lookahead 제약 안에는 역참조(back reference)를 넣을 수 없고, 안의 모든 괄호는 비캡처로 간주돼요. RE는 \로 끝날 수 없어요.

대괄호 표현식(BRACKET EXPRESSIONS)

대괄호 표현식은 [ ]로 감싼 문자 리스트예요. 보통 리스트에서 단일 문자 하나와 일치해요. 리스트가 ^로 시작하면 리스트의 나머지에 없는 단일 문자와 일치해요.

리스트에서 두 문자가 -로 구분되면, 콜레이팅 시퀀스에서 그 두 문자 사이(포함)의 전체 범위를 축약한 것이에요. 예를 들어 Unicode에서 [0-9]는 보통의 십진 숫자와 일치해요. 두 범위는 끝점을 공유할 수 없어서 a-c-e는 불법이에요. Tcl의 범위는 항상 Unicode 콜레이팅 시퀀스를 사용해요.

리터럴 ]-를 리스트에 포함하려면, 가장 간단한 방법은 [..]로 감싸 콜레이팅 요소로 만드는 거예요. 또는 첫 번째 문자(가능한 ^ 뒤)로 만들거나(ARE 전용) \로 앞에 붙여요. -의 경우 마지막 문자로 만들거나 범위의 두 번째 끝점으로 만들 수 있어요.

문자 클래스(CHARACTER CLASSES)

대괄호 표현식 안에서 [::]로 감싼 문자 클래스 이름은 해당 클래스에 속한 모든 문자(콜레이팅 요소가 아님!)의 리스트를 나타내요. 표준 문자 클래스는:

  • alpha — 문자
  • upper — 대문자
  • lower — 소문자
  • digit — 십진 숫자
  • xdigit — 16진수 숫자
  • alnum — 알파벳숫자(문자 또는 숫자)
  • print — "인쇄 가능"(graph와 같지만 공백도 포함)
  • blank — 공백 또는 탭 문자
  • space — 표시 텍스트에서 공백을 만드는 문자
  • punct — 구두점 문자
  • graph — 시각적 표현이 있는 문자(alnum과 punct 모두 포함)
  • cntrl — 제어 문자

로케일에 따라 다른 클래스가 제공될 수 있어요. 문자 클래스는 범위의 끝점으로 쓸 수 없어요. (참고: 현재 Tcl 구현에는 Unicode 로케일 하나만 있고, 정확히 위 클래스들을 지원해요.)

괄호로 감싼 제약(BRACKETED CONSTRAINTS)

대괄호 표현식의 특별한 경우로, [[:<:]][[:>:]]는 제약이에요. 각각 단어의 시작과 끝에서 빈 문자열과 일치해요. 단어는 앞뒤로 단어 문자가 없는 단어 문자 시퀀스로 정의돼요. 단어 문자는 alnum 문자 또는 밑줄(_)이에요. 이 특별한 표현식은 권장되지 않아요. ARE 사용자는 제약 이스케이프를 쓰는 게 좋아요.

콜레이팅 요소(COLLATING ELEMENTS)

대괄호 표현식 안에서 [..]로 감싼 콜레이팅 요소(문자, 단일 문자처럼 콜레이팅되는 다중 문자 시퀀스, 또는 그 중 하나의 콜레이팅 시퀀스 이름)는 그 콜레이팅 요소의 문자 시퀀스를 나타내요. 그 시퀀스는 대괄호 표현식 리스트의 단일 요소예요. 다중 문자 콜레이팅 요소가 있는 로케일의 대괄호 표현식은 한 개 이상의 문자와 일치할 수 있어요. (참고: Tcl에는 다중 문자 콜레이팅 요소가 없어요. 이 정보는 설명을 위한 것일 뿐이에요.)

예를 들어 콜레이팅 시퀀스에 ch 다중 문자 콜레이팅 요소가 있다고 가정해요. 그러면 RE "[[.ch.]]*c"(0개 이상의 "chs" 다음에 "c")는 "chchcc"의 처음 다섯 문자와 일치해요. 또한 RE "[^c]b""chb" 전체와 일치해요("[^c]"가 다중 문자 "ch"와 일치하니까).

등가 클래스(EQUIVALENCE CLASSES)

대괄호 표현식 안에서 [==]로 감싼 콜레이팅 요소는 등가 클래스로, 그 요소와 등가인 모든 콜레이팅 요소의 문자 시퀀스를 나타내요(자기 자신 포함). 예를 들어 o와 ô가 등가 클래스의 구성원이라면 "[[=o=]]", "[[=ô=]]", "[oô]"는 모두 동의어예요. 등가 클래스는 범위의 끝점일 수 없어요. (참고: Tcl은 Unicode 로케일만 구현하며 등가 클래스를 정의하지 않아요.)

이스케이프(ESCAPES)

이스케이프(ARE 전용)는 \ 다음에 알파벳숫자 문자가 오는 형태로 시작해요. 문자 입력, 클래스 축약, 제약, 역참조 등 여러 종류가 있어요. \ 뒤에 알파벳숫자 문자를 쓰되 유효한 이스케이프를 만들지 못하면 ARE에서 불법이에요. ERE에는 이스케이프가 없어요: 대괄호 표현식 밖에서 \ 뒤의 알파벳숫자 문자는 그 문자를 일반 문자로 취급할 뿐이고, 대괄호 표현식 안에서 \는 일반 문자예요.

문자 입력 이스케이프(CHARACTER-ENTRY ESCAPES)

  • \a — 경고(벨) 문자 (C처럼)
  • \b — 백스페이스 (C처럼)
  • \B\의 동의어로, 백슬래시 처리가 여러 단계인 애플리케이션에서 백슬래시 이중화를 줄이는 데 도움
  • \cX — (X는 임의의 문자) 하위 5비트가 X와 같고 나머지 비트가 모두 0인 문자
  • \e — 콜레이팅 시퀀스 이름이 ESC인 문자, 아니면 8진 값 033의 문자
  • \f — 폼피드 (C처럼)
  • \n — 개행 (C처럼)
  • \r — 캐리지 리턴 (C처럼)
  • \t — 가로 탭 (C처럼)
  • \uwxyz — (wxyz는 1~4자리 16진 숫자) 로컬 바이트 순서의 Unicode 문자 U+wxyz
  • \Ustuvwxyz — (stuvwxyz는 1~8자리 16진 숫자) 최대 21비트의 Unicode 확장용으로 예약. 첫 비16진 문자가 나올 때, 8자리 16진 숫자에 도달할 때, 또는 U+10ffff 최대값에서 오버플로가 일어날 때까지 숫자를 파싱
  • \v — 세로 탭 (C처럼)
  • \xhh — (hh는 1~2자리 16진 숫자) 16진 값이 0xhh인 문자
  • \0 — 값이 0인 문자
  • \xyz — (xyz는 정확히 3자리 8진 숫자, 역참조가 아님) 8진 값이 0xyz인 문자. 첫 번째 숫자는 0-3 범위여야 하며 그렇지 않으면 두 자리 형태로 간주
  • \xy — (xy는 정확히 2자리 8진 숫자, 역참조가 아님) 8진 값이 0xy인 문자

16진 숫자는 "0–9", "a–f", "A–F"이고, 8진 숫자는 "0–7"이에요. 문자 입력 이스케이프는 항상 일반 문자로 취급돼요. 예를 들어 \135는 Unicode에서 ]지만, \135는 대괄호 표현식을 끝내지 않아요. 다만 일부 애플리케이션(예: C 컴파일러, 그리고 정규식이 중괄호로 인용되지 않은 경우의 Tcl 인터프리터)이 정규식 패키지가 보기 전에 그런 시퀀스를 직접 해석하기도 하므로 \를 두 배(네 배 등)로 늘려야 할 수 있어요.

클래스 축약 이스케이프(CLASS-SHORTHAND ESCAPES)

  • \d[[:digit:]]
  • \s[[:space:]]
  • \w[[:alnum:]_ \u203F \u2040 \u2054 \uFE33 \uFE34 \uFE4D \uFE4E \uFE4F \uFF3F] (구두점 연결 문자 포함)
  • \D[^[:digit:]]
  • \S[^[:space:]]
  • \W[^[:alnum:]_...] (구두점 연결 문자 포함)

대괄호 표현식 안에서 \d, \s, \w는 바깥 괄호를 잃고, \D, \S, \W는 불법이에요. 예를 들어 [a-c\d][a-c[:digit:]]와 같고, [a-c\D][a-c^[:digit:]]와 같아서 불법이에요.

제약 이스케이프(CONSTRAINT ESCAPES)

  • \A — 문자열의 시작에서만 일치 (이것이 ^와 어떻게 다른지는 MATCHING 참조)
  • \m — 단어의 시작에서만 일치
  • \M — 단어의 끝에서만 일치
  • \y — 단어의 시작 또는 끝에서만 일치
  • \Y — 단어의 시작이나 끝이 아닌 지점에서만 일치
  • \Z — 문자열의 끝에서만 일치
  • \m — (m은 0이 아닌 숫자) 역참조
  • \mnn — (m은 0이 아닌 숫자, nn은 추가 숫자, 십진 값 mnn이 지금까지 본 닫힌 캡처 괄호 수 이하) 역참조

제약 이스케이프는 대괄호 표현식 안에서는 불법이에요.

역참조(BACK REFERENCES)

역참조(ARE 전용)는 숫자로 지정된 괄호 부표현식이 일치한 것과 같은 문자열과 일치해요. 예를 들어 "([bc])\1""bb""cc"와 일치하지만 "bc"는 아니에요. 부표현식은 RE 안에서 역참조보다 앞에 완전히 있어야 해요. 부표현식은 여는 괄호 순서대로 번호가 매겨지고, 비캡처 괄호는 부표현식을 정의하지 않아요.

8진 문자 입력 이스케이프와 역참조 사이에는 역사적 모호성이 있는데, 히스틱으로 해결돼요. 앞에 0이 오면 항상 8진 이스케이프예요. 다른 숫자가 뒤따르지 않는 단일 0이 아닌 숫자는 항상 역참조로 취급돼요. 0으로 시작하지 않는 다중 숫자 시퀀스는 적절한 부표현식 뒤에 오면(즉 역참조로 합법적 범위면) 역참조, 그렇지 않으면 8진으로 취급돼요.

메타문법(METASYNTAX)

일반적으로 사용되는 RE 계열은 애플리케이션 종속 방식으로 지정돼요. 하지만 디렉터(director)로 재정의할 수 있어요. 어떤 계열의 RE든 "***:"로 시작하면 나머지는 ARE예요. "***="로 시작하면 나머지는 리터럴 문자열로 취급돼 모든 문자가 일반 문자가 돼요.

ARE는 임베디드 옵션으로 시작할 수 있어요: (?xyz) 시퀀스(xyz는 하나 이상의 알파벳 문자)는 나머지 RE에 영향을 주는 옵션을 지정해요. 사용 가능한 옵션 문자는:

  • b — 나머지 RE는 BRE
  • c — 대소문자 구분 매칭 (보통 기본값)
  • e — 나머지 RE는 ERE
  • i — 대소문자 무시 매칭
  • m — n의 역사적 동의어
  • n — 개행 민감 매칭
  • p — 부분적 개행 민감 매칭
  • q — 나머지 RE는 리터럴("인용") 문자열, 모든 일반 문자
  • s — 비개행 민감 매칭 (보통 기본값)
  • t — 타이트 문법 (보통 기본값)
  • w — 역방향 부분 개행 민감("이상한") 매칭
  • x — 확장 문법

임베디드 옵션은 시퀀스를 끝내는 )에서 효력이 생겨요. ARE 시작에서만 사용 가능하고 그 이후에는 쓸 수 없어요.

보통의(타이트한) RE 문법 외에, 모든 문자가 의미 있는 형태, 모든 계열에서 -expanded 스위치로 또는 ARE에서 임베디드 x 옵션으로 쓸 수 있는 확장 문법이 있어요. 확장 문법에서 공백 문자는 무시되고 #와 다음 개행(또는 RE 끝) 사이의 모든 문자는 무시돼서, 복잡한 RE에 단락과 주석을 넣을 수 있어요. 기본 규칙에 세 가지 예외가 있어요: \가 앞에 온 공백 문자나 #는 유지되고, 대괄호 표현식 안의 공백이나 #는 유지되며, ARE의 (?:이나 BRE의 \( 같은 다중 문자 기호 안에서는 공백과 주석이 불법이에요.

마지막으로, ARE에서 대괄호 표현식 밖에서 (?#ttt) 시퀀스(ttt는 )를 포함하지 않는 임의 텍스트)는 완전히 무시되는 주석이에요. 이것 역시 (?: 같은 다중 문자 기호의 문자 사이에는 허용되지 않아요. 이런 주석은 유용한 기능이라기보다 역사적 유물에 가깝고, 사용이 권장되지 않아요. 확장 문법을 쓰세요.

애플리케이션(또는 처음의 ***= 디렉터)이 사용자 입력을 RE가 아니라 리터럴 문자열로 취급하도록 지정했다면 이런 메타문법 확장은 어느 것도 사용할 수 없어요.

매칭(MATCHING)

RE가 주어진 문자열에서 하나 이상의 부분 문자열과 일치할 수 있다면, 문자열에서 가장 일찍 시작하는 것을 매치해요. 그 지점에서 RE가 둘 이상의 부분 문자열과 일치할 수 있다면, 그 선택은 선호도에 따라 결정돼요: 가장 긴 부분 문자열 또는 가장 짧은 부분 문자열.

대부분의 원자와 모든 제약은 선호도가 없어요. 괄호로 묶인 RE는 RE와 같은 선호도를 가져요. {m} 또는 {m}? 양화자가 있는 양화 원자는 원자 자신과 같은 선호도를 가져요. 다른 일반 양화자(m이 n과 같은 {m,n} 포함)가 있는 양화 원자는 가장 긴 매치를 선호해요. 다른 비탐욕 양화자(m이 n과 같은 {m,n}? 포함)가 있는 양화 원자는 가장 짧은 매치를 선호해요. 브랜치는 그 안에서 선호도를 가진 첫 번째 양화 원자와 같은 선호도를 가져요. | 연산자로 연결된 두 개 이상의 브랜치로 된 RE는 가장 긴 매치를 선호해요.

전체 RE 매칭 규칙이 부과하는 제약 아래에서, 부표현식도 자신의 선호도에 따라 가능한 한 가장 길거나 짧은 부분 문자열과 일치해요. RE에서 더 일찍 시작하는 부표현식이 나중에 시작하는 것보다 우선해요. 그 결과 바깥 부표현식이 구성 요소 부표현식보다 우선해요.

양화자 {1,1}{1,1}?는 부표현식이나 전체 RE에 각각 최장/최단 선호도를 강제하는 데 사용할 수 있어요.

매치 길이는 콜레이팅 요소가 아닌 문자 단위로 측정돼요. 빈 문자열은 아예 매치가 없는 것보다 길다고 간주돼요. 대소문자 무시 매칭이 지정되면 알파벳에서 모든 대소문자 구별이 사라진 것과 같은 효과가 나요.

개행 민감 매칭이 지정되면 .^를 쓰는 대괄호 표현식은 새 개행 문자와 일치하지 않고, ^$는 문자열의 시작/끝에 더해 개행 앞뒤의 빈 문자열과도 일치해요. ARE의 \A\Z는 여전히 문자열 시작/끝에서만 일치해요.

제한과 호환성(LIMITS AND COMPATIBILITY)

RE 길이에는 특별한 제한이 없어요. 높은 이식성을 목표로 하는 프로그램은 256바이트를 넘는 RE를 쓰지 말아야 해요. POSIX 호환 구현이 그런 RE를 거부할 수 있기 때문이에요.

기본 정규식(BASIC REGULAR EXPRESSIONS)

BRE는 여러 면에서 ERE와 달라요. |, +, ?는 일반 문자이고 그 기능에 해당하는 게 없어요. 바운드 구분자는 \{\}이고, {}는 그 자체로 일반 문자예요. 중첩 부표현식의 괄호는 \(\)이며, ()는 그 자체로 일반 문자예요. ^는 RE 시작이나 괄호 부표현식 시작에서만 특수 문자이고, $는 RE 끝이나 괄호 부표현식 끝에서만 특수 문자이며, *는 RE 시작이나 괄호 부표현식 시작(가능한 앞의 ^ 뒤)에 나타나면 일반 문자예요. 마지막으로 한 자리 역참조를 쓸 수 있고, \<\>는 각각 [[:<:]][[:>:]]의 동의어이며, 다른 이스케이프는 없어요.

더 알아보기

  • RegExp, regexp, regsub: 정규식 매칭과 치환 명령
  • lsearch, switch, text: 정규식을 사용하는 다른 명령/위젯