regexp — 문자열에 정규식 매칭

regexp — 문자열에 정규식 매칭

어떤 문자열이 특정 패턴과 일치하는지 확인하고 싶을 때가 정말 많아요. regexp는 그런 정규식 매칭을 수행해 주는 명령이에요. 정규식 문법 자체에 대한 자세한 내용은 re_syntax 페이지를 따로 참고해야 하지만, 여기서는 regexp의 사용법과 각종 스위치를 집중적으로 다뤄요.

출처: 문서

본문

문법

regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?

동작 방식

regexp는 정규식 expstring의 일부 또는 전체와 일치하는지 판단해요. 일치하면 1, 일치하지 않으면 0을 반환하고, -inline이 지정된 경우는 예외예요(아래 참고).

string 이후에 추가 인자를 지정하면, string의 어느 부분이 exp와 일치했는지에 대한 정보를 반환할 변수 이름들로 취급돼요. matchVarexp 전체와 일치한 string의 범위로 설정되고, 첫 번째 subMatchVarexp 안의 가장 왼쪽 괄호로 묶인 부표현식과 일치한 문자들을 담고, 오른쪽으로 갈수록 다음 부표현식에 대응하는 변수들이 이어져요.

처음 인자가 -로 시작하면 스위치로 취급돼요. 지원되는 스위치는 다음과 같아요.

스위치

  • -about — 정규식 매칭을 시도하는 대신 정규식에 대한 정보를 담은 리스트를 반환해요. 리스트의 첫 요소는 부표현식 개수, 둘째 요소는 정규식의 여러 속성을 설명하는 속성 이름 리스트예요. 주로 디버깅 목적으로 사용돼요.
  • -expanded — 공백과 주석이 무시되는 확장 정규식 문법을 사용하게 해요. (?x) 임베디드 옵션을 지정하는 것과 같아요.
  • -indicesmatchVarsubMatchVar에 저장되는 내용을 바꿔요. 일치하는 문자를 저장하는 대신, 각 변수는 일치 범위의 첫 번째와 마지막 문자에 대한 string 안의 인덱스를 주는 두 개의 십진 문자열 리스트를 담아요.
  • -line — 줄바꿈 민감 매칭을 활성화해요. 기본적으로 줄바꿈은 특별한 의미가 없는 완전히 평범한 문자예요. 이 플래그를 쓰면 [^ 대괄호 표현식과 .가 줄바꿈과 절대 일치하지 않고, ^는 정상 기능에 더해 어떤 줄바꿈 뒤의 빈 문자열과도 일치하며, $는 정상 기능에 더해 어떤 줄바꿈 앞의 빈 문자열과도 일치해요. -linestop-lineanchor를 둘 다 지정한 것, 또는 (?n) 임베디드 옵션과 같아요.
  • -linestop[^ 대괄호 표현식과 .의 동작을 바꿔서 줄바꿈에서 멈추게 해요. (?p) 옵션과 같아요.
  • -lineanchor^$("앵커")의 동작을 바꿔 각각 줄의 시작과 끝과 일치하게 해요. (?w) 옵션과 같아요.
  • -nocase — 매칭 과정에서 string의 대문자를 소문자로 취급하게 해요.
  • -all — 정규식을 문자열에서 가능한 한 많이 일치시켜, 찾은 총 매치 수를 반환하게 해요. 매치 변수와 함께 지정하면 변수들은 마지막 매치에 대한 정보만 담아요.
  • -inline — 명령이 매치 변수에 넣을 데이터를 대신 리스트로 반환하게 해요. -inline을 쓸 때는 매치 변수를 지정할 수 없어요. -all과 함께 쓰면 각 반복마다 리스트가 이어져 항상 평평한 리스트가 반환돼요. 매치 반복마다 전체 매치 데이터에 정규식의 각 부표현식마다 한 요소씩을 추가해서 반환해요. 예:
    regexp -inline -- {\w(\w)} " inlined "
    → in n
    regexp -all -inline -- {\w(\w)} " inlined "
    → in n li i ne e
    
  • -start index — 정규식 매칭을 시작할 문자열 안의 문자 인덱스 오프셋을 지정해요. 이 인덱스 값은 string index의 인덱스 인자와 같은 방식으로 해석돼요. 이 스위치를 쓸 때 ^는 줄의 시작과 일치하지 않고, \\A는 여전히 index에서의 문자열 시작과 일치해요. -indices가 지정되면 인덱스는 입력 문자열의 절대 시작부터 세어요. index는 입력 문자열의 범위로 제한돼요.
  • -- — 스위치의 끝을 표시해요. 다음 인자는 -로 시작하더라도 exp로 취급돼요.

subMatchVarexp 안의 괄호 부표현식보다 많거나, 특정 부표현식이 문자열과 일치하지 않으면(예를 들어 일치하지 않은 표현식 부분에 있었기 때문에), 해당 subMatchVar-indices가 지정됐다면 "-1 -1"로, 그렇지 않으면 빈 문자열로 설정돼요.

예제

foobar의 실제 인스턴스가 아닌, foo로 시작하는 단어가 문자열에 처음 나타나는 위치를 찾고 그 뒤의 문자들을 단어 끝까지 변수로 가져오기:

regexp {\mfoo(?!bar\M)(\w*)} $string -> restOfWord

문자열 안에서 단어 badger(대소문자 무관)의 인덱스를 찾아 변수 location에 저장하기:

regexp -indices {(?i)\mbadger\M} $string location

이건 기본 문법인 고급 정규식 대신 기본 정규식으로도 쓸 수 있어요. 표현식 앞에 적절한 플래그를 붙이면 되죠:

regexp -indices {(?ib)\<badger\>} $string location

문자열 안의 8진수 자릿수 개수 세기:

regexp -all {[0-7]} $string

문자열 안의 모든 단어(비공백 문자의 모든 시퀀스)를 나열하기. split 명령보다 더 강력한 버전으로 유용해요:

regexp -all -inline {\S+} $string

더 알아보기

  • re_syntax: Tcl 정규식 문법 전체 참조
  • regsub: 정규식 기반 치환
  • string: 문자열 조작