re — 정규 표현식 연산¶
소스 코드: Lib/re/
이 모듈은 Perl에 있는 것과 유사한 정규식 일치 연산을 제공합니다.
검색할 패턴과 문자열은 유니코드 문자열 (str)일 수도 있고 8비트 문자열 (bytes)일 수도 있습니다. 하지만, 유니코드 문자열과 8비트 문자열을 혼합할 수는 없습니다. 즉, 바이트 패턴으로 유니코드 문자열을 매칭하거나 그 반대의 경우 모두 할 수 없으며; 마찬가지로, 치환할 문자열은 패턴 및 검색 문자열과 동일한 유형이어야 합니다.
정규식은 백슬래시 문자 ('\\')를 사용하여 특수 형식을 나타내거나 특수 문자를 특별한 의미를 부여받지 않고 사용할 수 있도록 합니다. 이것은 파이썬에서 문자열 리터럴 내에 같은 목적으로 동일한 문자를 사용하는 것과 충돌합니다. 예를 들어, 리터럴 백슬래시를 매칭하려면 패턴 문자열로 '\\\\\\' 를 작성해야 할 수도 있습니다. 이는 정규 표현식이 \\ 여야 하며, 각 백슬래시는 일반 파이썬 문자열 리터럴 내부에서 \\ 로 표현되어야 하기 때문입니다. 또한, 파이썬의 문자열 리터럴에서 백슬래시 사용 시 발생하는 모든 유효하지 않은 이스케이프 시퀀스는 이제 SyntaxWarning 을 발생시키며 미래에는 SyntaxError 가 될 것임을 참고하십시오. 이 동작은 정규 표현식에 대한 유효한 이스케이프 시퀀스일지라도 발생합니다.
해결책은 정규식 패턴에 파이썬의 날 문자열(raw string) 표기법을 사용하는 것입니다; 역 슬래시는 'r' 접두어가 붙은 문자열 리터럴에서 특별한 방법으로 처리되지 않습니다. 따라서 r"\n"은 '\'와 'n'을 포함하는 두 글자 문자열이고, "\n"은 개행을 포함하는 한 글자 문자열입니다. 일반적으로 패턴은, 이 날 문자열 표기법을 사용하여 파이썬 코드로 표현됩니다.
대부분 정규식 연산은 모듈 수준 함수와 컴파일된 정규식의 메서드로 사용할 수 있다는 점에 유의해야 합니다. 함수는 정규식 객체를 먼저 컴파일할 필요가 없도록 하는 바로 가기이지만, 일부 미세 조정 매개 변수가 빠져있습니다.
더 보기
타사 regex 모듈은 표준 라이브러리 re 모듈과 호환되는 API를 가지지만, 추가적인 기능과 보다 포괄적인 유니코드 지원을 제공합니다.
정규 표현식 구문¶
정규식(또는 RE)은 일치하는 문자열 집합을 지정합니다; 이 모듈의 함수는 특정 문자열이 주어진 정규식과 일치하는지 확인할 수 있도록 합니다 (또는 주어진 정규식이 특정 문자열과 일치하는지, 결국 같은 결과를 줍니다).
정규식을 이어붙여서 새로운 정규식을 만들 수 있습니다; A와 B가 모두 정규식이면 AB도 정규식입니다. 일반적으로 문자열 p가 A와 일치하고 다른 문자열 q가 B와 일치하면 문자열 pq가 AB와 일치합니다. 이것은 A나 B가 우선순위가 낮은 연산, A와 B 사이의 경계 조건 또는 숫자 그룹 참조를 포함하지 않는 한 성립합니다. 따라서, 복잡한 정규식은 여기에 설명된 것과 같은 더 단순한 기본 정규식으로 쉽게 구성할 수 있습니다. 정규식의 이론과 구현에 관한 자세한 내용은 Friedl 책 [Frie09], 또는 컴파일러 작성에 관한 거의 모든 교과서를 참조하십시오.
정규식의 형식에 대한 간단한 설명이 이어집니다. 더 자세한 정보와 더 친절한 소개는 정규식 HOWTO를 참조하십시오.
정규식은 특수 문자와 일반 문자를 모두 포함 할 수 있습니다. 'A', 'a' 또는 '0'과 같은 대부분의 일반 문자는 가장 단순한 정규식입니다; 그들은 단순히 자신과 일치합니다. 일반 문자를 이어 붙일 수 있어서, last는 'last' 문자열과 일치합니다. (이 절의 나머지 부분에서는, RE를 (보통 따옴표 없이) 이런 특별한 스타일로, 일치할 문자열은 '작은따옴표 안에' 씁니다.)
'|'나 '('와 같은 일부 문자는 특수합니다. 특수 문자는 일반 문자의 클래스를 나타내거나, 그 주변의 정규식이 해석되는 방식에 영향을 줍니다.
Repetition operators or quantifiers (*, +, ?, {m,n}, etc) cannot be
directly nested. This avoids ambiguity with the non-greedy modifier suffix
?, and with other modifiers in other implementations. To apply a second
repetition to an inner repetition, parentheses may be used. For example,
the expression (?:a{6})* matches any multiple of six 'a' characters.
특수 문자는 다음과 같습니다:
.(Dot.) 기본 모드에서는 줄 바꿈 문자를 제외한 모든 문자와 일치합니다.
DOTALL플래그가 지정된 경우, 이 문자는 줄 바꿈을 포함하여 모든 문자와 일치합니다.(?s:.)는 어떤 플래그와 관계없이 모든 문자와 일치합니다.
^(캐럿.) 문자열의 시작과 일치하고,
MULTILINE모드에서는 각 개행 직후에도 일치합니다.
$문자열의 끝이나 문자열 끝의 개행 문자 바로 직전과 일치하고,
MULTILINE모드에서는 개행 문자 앞에서도 일치합니다.foo는 ‘foo’와 ‘foobar’를 모두 일치시키는 반면, 정규식foo$는 ‘foo’ 만 일치합니다. 흥미롭게도,'foo1\nfoo2\n'에서foo.$를 검색하면 ‘foo2’ 는 정상적으로 일치되지만, ‘foo1’은MULTILINE모드에서 검색됩니다;'foo\n'에서 단일$를 검색하면 두 개의 (빈) 일치가 발견됩니다: 하나는 개행 직전에, 다른 하나는 문자열 끝에.
*결과 RE가 선행 RE의 가능한 한 많은 0회 이상의 반복과 일치하도록 합니다.
ab*는 ‘a’, ‘ab’ 또는 ‘a’ 다음에 임의의 수의 ‘b’가 오는 것과 일치합니다.
+결과 RE가 선행 RE의 1회 이상의 반복과 일치하도록 합니다.
ab+는 ‘a’ 다음에 하나 이상의 ‘b’가 오는 것과 일치합니다; 단지 ‘a’와는 일치하지 않습니다.
?결과 RE가 선행 RE의 0 또는 1 반복과 일치하도록 합니다.
ab?는 ‘a’나 ‘ab’와 일치합니다.
*?,+?,??퀀티파이어인
'*','+','?'는 모두 탐욕적(greedy) 이며 가능한 한 많은 텍스트와 일치합니다. 때때로 이 동작이 원하는 것이 아닐 수 있습니다. RE<.*>가'<a> b <c>'에 매칭되면 전체 문자열을 매칭하며, 단순히'<a>'만을 매칭하지 않습니다. 양자 구문 뒤에?를 추가하면 비탐욕적(non-greedy) 또는 최소한의(minimal) 방식으로 동작하여 가능한 한 적은 문자가 일치하게 됩니다. RE<.*?>을 사용하면'<a>'만을 매칭합니다.
*+,++,?+'*'와'+'그리고'?'와 같은 한정자들처럼, 뒤에'+'가 붙은 것도 가능한 최대 횟수만큼 일치합니다. 그러나 진짜 탐욕적(greedy) 한정자와 달리, 이것들은 후속 표현이 일치하지 않을 때 백트래킹을 허용하지 않습니다. 이들은 소유(possessive) 한정자라고 알려져 있습니다. 예를 들어,a*a는'aaaa'와 일치합니다. 왜냐하면a*가 모든 4개의'a'를 일치시키기 때문이지만, 마지막'a'에 도달했을 때, 이 표현식은 백트래킹되어 결국a*는 총 3개의'a'만 일치시키고 네 번째'a'가 마지막'a'에 의해 일치하게 됩니다. 그러나a*+a를 사용하여'aaaa'와 일치하려고 할 때,a*+는 모든 4개의'a'를 일치시킵니다. 하지만 마지막'a'가 더 이상 일치할 문자를 찾지 못하면, 표현식은 백트래킹될 수 없으므로 결국 일치에 실패합니다.x*+,x++및x?+는 각각(?>x*),(?>x+), 그리고(?>x?)와 같습니다.Added in version 3.11.
{m}선행 RE의 정확히 m 복사가 일치하도록 지정합니다; 적은 횟수의 일치는 전체 RE가 일치하지 않게 됩니다. 예를 들어,
a{6}는 정확히 6개의'a'문자와 일치하지만, 5개의 문자와는 일치하지 않습니다.{m,n}결과 RE를 선행 RE의 m에서 n 사이의 최대한 많은 반복과 일치하도록 합니다. 예를 들어,
a{3,5}는 3에서 5개의'a'문자와 일치합니다. m을 생략하면 하한값 0이 지정되고, n을 생략하면 무한한 상한이 지정됩니다. 예를 들어,a{4,}b는'aaaab'나 1000개의'a'문자와'b'가 일치하지만,'aaab'는 일치하지 않습니다. 콤마는 생략할 수 없습니다, 그렇지 않으면 한정자가 앞에서 설명한 형식과 혼동될 수 있습니다.{m,n}?앞선 정규 표현식의 반복을 m 에서 n 회까지 발생하도록 하여 가능한 한 가장 적은 횟수의 반복과 일치하려고 합니다. 이는 이전의 한정자의 비탐욕적(non-greedy) 버전입니다. 예를 들어, 6문자열
'aaaaaa'에 대해,a{3,5}는 5개의'a'문자와 일치하는 반면,a{3,5}?는 3개의 문자만 일치시킵니다.{m,n}+결과 RE를 앞선 RE의 m 에서 n 회 반복하되, 어떤 백트래킹 지점도 설정하지 않는 방식으로 가능한 한 많은 횟수만큼 일치시키도록 합니다. 이는 위 한정자의 소유(possessive) 버전입니다. 예를 들어, 6문자열
'aaaaaa'에 대해,a{3,5}+aa는 5개의'a'문자를 일치시키려고 시도한 다음, 필요한 2개의 추가적인'a'를 요구하면서 사용 가능한 것보다 더 많은 문자가 필요하여 실패합니다. 반면,a{3,5}aa는a{3,5}가 5개를 캡처하고, 그 후 백트래킹을 통해 4개의'a'를 일치시킨 다음, 마지막의 2개'a'는aa에 의해 일치시킵니다.x{m,n}+는(?>x{m,n})와 같습니다.Added in version 3.11.
\특수 문자를 이스케이프 하거나 (
'*','?'등의 문자를 일치시킬 수 있도록 합니다), 특수 시퀀스를 알립니다; 특수 시퀀스는 아래에서 설명합니다.날 문자열을 사용하여 패턴을 표현하지 않는다면, 파이썬이 문자열 리터럴에서 이스케이프 시퀀스로 역 슬래시를 사용한다는 것을 기억하십시오; 이스케이프 시퀀스가 파이썬의 구문 분석기에 의해 인식되지 않으면, 역 슬래시와 후속 문자가 결과 문자열에 포함됩니다. 그러나 파이썬이 결과 시퀀스를 인식한다면 역 슬래시는 두 번 반복되어야 합니다. 이것은 복잡하고 이해하기 어렵기 때문에, 가장 단순한 표현 이외에는 날 문자열을 사용하는 것이 좋습니다.
[]문자 집합을 나타내는 데 사용됩니다. 집합 안에서:
문자는 개별적으로 나열 할 수 있습니다, 예를 들어
[amk]는'a','m'또는'k'와 일치합니다.
문자의 범위는
'-'로 구분된 두 문자를 주고는 것으로 나타낼 수 있습니다, 예를 들어[a-z]는 모든 소문자 ASCII 문자와 일치하고,[0-5][0-9]는00에서59까지의 모든 두 자리 숫자와 일치하며,[0-9A-Fa-f]는 모든 16진수와 일치합니다.-가 이스케이프 처리되거나 (예를 들어[a\-z]) 첫 번째나 마지막 문자로 배치되면 (예를 들어[-a]나[a-]) 리터럴'-'와 일치합니다.백슬래시()를 제외한 특수 문자는 집합 내에서 그 특수한 의미를 잃습니다. 예를 들어,
[(+*)]``는 리터럴 문자 ``'(','+','*', 또는')'중 어느 것과도 일치합니다.
백슬래시는 집합에서 특수 의미를 갖는 문자를 이스케이프하거나(예:
'-',']','^'및'\\'자체), 또는\xa0나\n와 같은 단일 문자를 나타내거나\w나\S와 같은 문자 클래스를 나타내는 특수 시퀀스를 신호합니다 (아래 정의됨). 참고로,\b는 단어 경계가 아닌 단일 “백스페이스” 문자를 나타내며,\1과 같은 숫자 이스케이프는 항상 8진수 이스케이프이며 그룹 참조가 아닙니다.\A및\z와 같이 단일 문자와 일치하지 않는 특수 시퀀스는 허용되지 않습니다.
범위 내에 있지 않은 문자는 여집합(complementing)을 만들어 일치할 수 있습니다. 집합의 첫 번째 문자가
'^'이면, 집합에 속하지 않은 모든 문자가 일치합니다. 예를 들어,[^5]는'5'를 제외한 모든 문자와 일치하며,[^^]는'^'를 제외한 모든 문자와 일치합니다.^는 집합의 첫 번째 문자가 아닐 때 특별한 의미가 없습니다.집합 내에서 리터럴 ‘]’`를 일치시키려면, 이를 백슬래시로 접두하거나 집합의 시작 부분에 위치시켜야 합니다. 예를 들어, ``[()[]{}]``와 ``[]()[{}]` 모두 오른쪽 대괄호는 물론, 왼쪽 대괄호, 중괄호, 괄호와도 일치합니다.
유니코드 기술 표준 #18 에서 정의하는 중첩 집합과 집합 연산의 지원이 다음에 추가될 수 있습니다. 이것은 문법을 변경하므로, 이 변경을 용이하게 하기 위해 당분간
FutureWarning이 모호한 경우에 발생합니다. 여기에는 리터럴'['로 시작하거나 리터럴 문자 시퀀스'--','&&','~~'및'||'가 포함된 집합이 포함됩니다. 경고를 피하려면 역 슬래시로 이스케이프 처리하십시오.
버전 3.7에서 변경: 문자 집합이 미래에 의미가 변할 구조를 포함하고 있다면
FutureWarning이 발생합니다.
|A|B(여기서 A와 B는 임의의 RE일 수 있습니다)는 A나 B와 일치하는 정규식을 만듭니다. 이러한 방식으로 임의의 수의 RE를'|'로 분리 할 수 있습니다. 이것은 그룹(아래를 참조하세요)에서도 사용할 수 있습니다. 대상 문자열이 스캔 될 때'|'로 구분된 RE는 왼쪽에서 오른쪽으로 시도됩니다. 한 패턴이 완전히 일치하면, 해당 분기가 받아들여집니다. 이는 일단 A가 일치하면, B는 전체적으로 더 긴 일치를 생성하더라도 더 검사되지 않는다는 것을 뜻합니다. 즉,'|'연산자는 절대로 탐욕적이지 않습니다. 리터럴'|'와 일치시키려면,\|를 사용하거나,[|]처럼 문자 클래스 안에 넣으십시오.
(...)괄호 안에 있는 정규식과 일치하며, 그룹의 시작과 끝을 나타냅니다; 그룹의 내용은 일치가 수행된 후 조회할 수 있으며, 나중에 문자열에서
\number특수 시퀀스로 일치시킬 수 있습니다 (아래에서 설명됩니다). 리터럴'('나')'를 일치시키려면,\(나\)를 사용하거나, 문자 클래스 안에 넣으십시오:[(],[)].
(?...)이것은 확장 표기법입니다 (그렇지 않으면
'('다음에 오는'?'는 의미가 없습니다).'?'다음의 첫 번째 문자는 확장의 의미와 이후의 문법을 결정합니다. 확장은 대개 새 그룹을 만들지 않습니다; 이 규칙에 대한 유일한 예외는(?P<name>...)입니다. 다음은 현재 지원되는 확장입니다.(?aiLmsux)(집합
'a','i','L','m','s','u','x'\의 문자 중 하나 이상.) 이 그룹은 빈 문자열과 일치하며; 문자는 전체 정규식에 대해 해당 플래그를 설정합니다:re.A(ASCII만 일치)re.I(대소문자 무시)re.L(로케일 종속)re.M(여러 줄)re.S(점은 모든 문자와 일치)re.U(유니코드 일치)re.X(자세 모드)
(플래그는 모듈 내용\에 설명되어 있습니다.) 이 방법은 flag 인자를
re.compile()함수에 전달하는 대신, 플래그를 정규식의 일부로 포함하려는 경우 유용합니다. 플래그는 표현식 문자열에서 먼저 사용해야 합니다.버전 3.11에서 변경: 이 구문은 표현식의 시작 부분에서만 사용될 수 있습니다.
(?:...)일반 괄호의 비 포착 버전. 괄호 안의 정규식과 일치하지만, 그룹과 일치하는 부분 문자열은 일치를 수행한 후 조회하거나 나중에 패턴에서 참조할 수 없습니다.
(?aiLmsux-imsx:...)(집합
'a','i','L','m','s','u','x'\의 문자 중 0개 이상이거나, 선택적으로'-'뒤에 하나 이상의'i','m','s','x'중 하나가 따라오는 형태입니다. 이 문자는 표현식의 부분에 대해 해당하는 플래그를 설정하거나 제거합니다:re.A(ASCII만 일치)re.I(대소문자 무시)re.L(로케일 종속)re.M(여러 줄)re.S(점은 모든 문자와 일치)re.U(유니코드 일치)re.X(자세 모드)
(플래그는 모듈 내용\에 설명되어 있습니다.)
문자
'a','L'그리고'u'는 인라인 플래그로 사용될 때 서로 배타적이므로 결합되거나'-'뒤에 올 수 없습니다. 대신, 이 중 하나가 인라인 그룹 내에 나타나면, 해당 열거된 그룹의 일치 모드를 덮어씁니다. 유니코드 패턴(?a:...)은 ASCII 전용 일치로 전환되며,(?u:...)은 유니코드 일치를 전환합니다 (기본값). 바이트 패턴(?L:...)는 로케일 의존적 일치로 전환되고,(?a:...)은 ASCII 전용 일치로 전환합니다 (기본값). 이 덮어쓰기는 좁은 인라인 그룹에 대해서만 유효하며, 원래의 일치 모드는 그룹 외부에서 복원됩니다.Added in version 3.6.
버전 3.7에서 변경: 문자
'a','L'및'u'도 그룹에서 사용할 수 있습니다.(?>...)...가 별도의 정규 표현식인 것처럼 일치하려 시도하고, 성공하면 뒤따르는 나머지 패턴까지 계속 일치합니다. 후속 패턴이 일치하지 않으면 스택은(?>...)보다 이전 지점까지만 풀릴 수 있습니다. 왜냐하면 한 번 벗어나면, 원자적 그룹 으로 알려진 이 표현식은 그 자체 내의 모든 스택 포인트를 버렸기 때문입니다. 따라서,(.*?)\\.` 같은 패턴은 결코 어떤 것도 일치시키지 못합니다. 첫 번째로 `.*` 가 가능한 모든 문자와 일치시키고, 그러고 나니 더 이상 일치시킬 것이 남아 있지 않아 마지막 ``.이 실패하기 때문입니다. 원자적 그룹에는 스택 포인트가 저장되어 있지 않고, 그 앞에도 스택 포인트가 없기 때문에 전체 표현식은 일치하지 못하게 됩니다.Added in version 3.11.
(?P<name>...)정규 괄호와 유사하지만, 해당 그룹과 일치하는 부분 문자열은 상징적 그룹 이름 name 을 통해 접근할 수 있습니다. 그룹 이름은 유효한 Python 식별자여야 하며,
bytes패턴에서는 ASCII 범위 내의 바이트만 포함할 수 있습니다. 각 그룹 이름은 정규 표현식 내에서 한 번만 정의되어야 합니다. 상징적 그룹은 또한, 마치 그룹에 이름이 없는 것처럼 번호가 매겨진 그룹입니다.이름 있는 그룹은 세 가지 문맥에서 참조될 수 있습니다. 패턴이
(?P<quote>['"]).*?(?P=quote)면 (즉, 작은따옴표나 큰따옴표로 인용된 문자열과 일치):그룹 “quote”에 대한 참조 문맥
참조하는 방법
같은 패턴 자체에서
(?P=quote)(보이는 대로)\1
일치 객체 m을 처리할 때
m.group('quote')m.end('quote')(등)
re.sub()의 repl 인자로 전달되는 문자열에서\g<quote>\g<1>\1
버전 3.12에서 변경:
bytes패턴에서 그룹 name 은 ASCII 범위의 바이트 (b'\x00'-b'\x7f')만 포함할 수 있습니다.
(?P=name)이름있는 그룹에 대한 역참조; name이라는 이름의 앞선 그룹과 일치하는 텍스트와 일치합니다.
(?#...)주석; 괄호의 내용은 단순히 무시됩니다.
(?=...)...가 다음과 일치하면 일치하지만, 문자열을 소비하지는 않습니다. 이를 미리 보기 어서션 (lookahead assertion)이라고 합니다. 예를 들어,Isaac (?=Asimov)는'Asimov'가 뒤따를 때만'Isaac '과 일치합니다.
(?!...)...가 다음과 일치하지 않으면 일치합니다. 이것은 부정적인 미리 보기 어서션 (negative lookahead assertion)입니다. 예를 들어,Isaac (?!Asimov)는'Asimov'가 뒤따르지 않을 때 만'Isaac '과 일치합니다.
(?<=...)문자열의 현재 위치 앞에 현재 위치에서 끝나는
...와의 일치가 있으면 일치합니다. 이를 긍정적인 되돌아보기 어서션 (positive lookbehind assertion)이라고 합니다. 되돌아보기가 3문자를 백업하고 포함된 패턴이 일치하는지 확인하기 때문에(?<=abc)def는'abcdef'에서 일치를 찾습니다. 포함된 패턴은 고정 길이의 문자열과 일치해야 합니다, 즉,abc나a|b는 허용되지만,a*와a{3,4}는 허용되지 않습니다. 긍정적인 되돌아보기 어서션으로 시작하는 패턴은 검색되는 문자열의 시작 부분에서 일치하지 않음에 유의하십시오;match()함수보다는search()함수를 사용하기를 원할 것입니다:>>> import re >>> m = re.search('(?<=abc)def', 'abcdef') >>> m.group(0) 'def'
이 예에서는 하이픈 다음의 단어를 찾습니다:
>>> m = re.search(r'(?<=-)\w+', 'spam-egg') >>> m.group(0) 'egg'
버전 3.5에서 변경: 고정 길이의 그룹 참조에 대한 지원이 추가되었습니다.
(?<!...)문자열의 현재 위치 앞에
...와의 일치가 없으면 일치합니다. 이를 부정적인 뒤돌아보기 어서션 (negative lookbehind assertion)이라고 합니다. 긍정적인 뒤돌아보기 어서션과 마찬가지로, 포함된 패턴은 고정 길이의 문자열과 일치해야 합니다. 부정적인 뒤돌아보기 어서션으로 시작하는 패턴은 검색되는 문자열의 시작 부분에서 일치 할 수 있습니다.
(?(id/name)yes-pattern|no-pattern)주어진 id나 name의 그룹이 있으면
yes-pattern과, 그렇지 않으면no-pattern과 일치하려고 시도합니다.no-pattern은 선택적이며 생략될 수 있습니다. 예를 들어,(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)는 정교하지 않은 전자 메일 일치 패턴인데,'<user@host.com>'및'user@host.com'과 일치하지만,'<user@host.com'이나'user@host.com>'과는 일치하지 않습니다.버전 3.12에서 변경: 그룹 id 는 ASCII 숫자만 포함할 수 있습니다.
bytes패턴에서 그룹 name 은 ASCII 범위의 바이트 (b'\x00'-b'\x7f')만 포함할 수 있습니다.
특수 시퀀스는 '\'와 아래 목록의 문자로 구성됩니다. 일반 문자가 ASCII 숫자나 ASCII 글자가 아니면, 결과 RE는 두 번째 문자와 일치합니다. 예를 들어, \$는 문자 '$'와 일치합니다.
\number같은 번호의 그룹 내용과 일치합니다. 그룹은 1부터 번호가 매겨집니다. 예를 들어,
(.+) \1은'the the'나'55 55'와 일치하지만,'thethe'와는 일치하지 않습니다 (그룹 뒤의 공백에 유의하십시오). 이 특수 시퀀스는 첫 99개 그룹 중 하나와 일치하는 데에만 사용될 수 있습니다. number의 첫 자릿수가 0이거나, number가 3 자릿수면, 그룹 일치로 해석되지 않고, 8진수 값 number를 갖는 문자로 해석됩니다. 문자 클래스의'['와']'안에서는, 모든 숫자 이스케이프가 문자로 처리됩니다.
\A문자열의 시작 부분에서만 일치합니다.
\b비어 있는 문자열과 일치하며, 단어의 시작 또는 끝에만 해당합니다. 단어는 일련의 단어 문자로 정의됩니다. 공식적으로 볼 때,
\b는\w와\W문자(또는 그 반대) 사이, 또는\w와 문자열의 시작이나 끝 사이의 경계로 정의됩니다. 이는r'\bat\b'이'at','at.','(at)', 그리고'as at ay'와 일치하지만,'attempt'또는'atlas'와는 일치하지 않음을 의미합니다.유니코드 (str) 패턴의 기본 단어 문자는 유니코드 영숫자와 밑줄이지만,
ASCII플래그를 사용하여 변경할 수 있습니다. 단어 경계는LOCALE플래그를 사용하면 현재 로케일에 의해 결정됩니다.참고
문자 범위 내에서,
\b는 Python 문자열 리터럴과의 호환성을 위해 백스페이스 문자를 나타냅니다.
\B비어 있는 문자열과 일치하지만, 단어의 시작이나 끝이 아닐 때만 해당합니다. 이는
r'at\B'가'athens','atom','attorney'와 일치하지만,'at','at.'또는'at!'와는 일치하지 않음을 의미합니다.\B는\b의 반대이므로, 유니코드 (str) 패턴에서 단어 문자는 유니코드 영숫자나 밑줄이며, 비록ASCII플래그를 사용하여 변경될 수 있습니다. 단어 경계는LOCALE플래그를 사용하면 현재 로케일에 의해 결정됩니다.버전 3.14에서 변경:
\B는 이제 빈 문자열과 일치합니다.
\d
\D십진 숫자가 아닌 모든 문자와 일치합니다. 이는
\d의 반대입니다.ASCII플래그를 사용하면[^0-9]와 일치합니다.
\s- 유니코드 (str) 패턴일 때:
유니코드 공백 문자(
str.isspace()에 의해 정의됨)와 일치합니다. 여기에는[ \t\n\r\f\v]뿐만 아니라, 예를 들어 많은 언어의 타이포그래피 규칙에서 요구하는 공백 파기 공백도 포함됩니다.ASCII플래그를 사용하면[ \t\n\r\f\v]와 일치합니다.- 8비트 (bytes) 패턴일 때:
ASCII 문자 집합에서 공백으로 간주하는 문자와 일치합니다; 이것은
[ \t\n\r\f\v]와 동등합니다.
\S공백 문자가 아닌 모든 문자와 일치합니다. 이것은
\s\의 반대입니다.ASCII플래그가 사용되면[^ \t\n\r\f\v]와 일치합니다.
\w- 유니코드 (str) 패턴일 때:
유니코드 단어 문자와 일치하며; 여기에는 모든 유니코드 영숫자 문자 (
str.isalnum()\에 의해 정의됨) 및 밑줄 (_)\도 포함됩니다.ASCII플래그가 사용되면[a-zA-Z0-9_]와 일치합니다.- 8비트 (bytes) 패턴일 때:
ASCII 문자 집합에서 영숫자로 간주되는 문자와 일치합니다; 이는
[a-zA-Z0-9_]\와 동등합니다.LOCALE플래그를 사용하면, 현재 로케일에서 영숫자로 간주되고 밑줄을 포함하는 문자와 일치합니다.
\W단어 문자가 아닌 모든 문자와 일치합니다. 이것은
\w\의 반대입니다. 기본적으로,str.isalnum()가False를 반환하는 밑줄이 아닌 문자와 일치합니다.ASCII플래그가 사용되면[^a-zA-Z0-9_]와 일치합니다.LOCALE플래그가 사용되면, 현재 로케일에서 영숫자로도 밑줄로도 간주되지 않는 문자와 일치합니다.
\z문자열 끝에만 일치합니다.
Added in version 3.14.
\Z\z와 동일합니다. 이전 버전의 Python과의 호환성을 위해입니다.
Python 문자열 리터널에서 지원되는 대부분의 :ref:`escape sequences <escape-sequences>`도 정규 표현식 파서에 의해 받아들여집니다:
\a \b \f \n
\N \r \t \u
\U \v \x \\
(\b는 단어 경계를 나타내는 데 사용되며, 문자 클래스 내에서만 “백스페이스”를 의미함에 유의하십시오.)
'\u', '\U', 및 '\N'\ 이스케이프 시퀀스는 유니코드 (str) 패턴에서만 인식됩니다. bytes 패턴에서는 오류입니다. ASCII 문자의 알 수 없는 이스케이프는 향후 사용을 위해 예약되며 오류로 처리됩니다.
8진수 이스케이프는 제한된 형식으로 포함됩니다. 첫 번째 숫자가 0이거나, 3개의 8진수가 있으면, 8진수 이스케이프로 간주합니다. 그렇지 않으면, 그룹 참조입니다. 문자열 리터럴과 마찬가지로, 8진수 이스케이프 길이는 항상 최대 3자리입니다.
버전 3.3에서 변경: '\u'와 '\U' 이스케이프 시퀀스가 추가되었습니다.
버전 3.6에서 변경: '\'와 ASCII 글자로 구성된 알 수 없는 이스케이프는 이제 에러입니다.
버전 3.8에서 변경: '\N{name}' 이스케이프 시퀀스가 추가되었습니다. 문자열 리터럴과 마찬가지로, 이름 지정된 유니코드 문자로 확장됩니다 (예.: '\N{EM DASH}').
모듈 내용¶
모듈은 몇 가지 함수, 상수 및 예외를 정의합니다. 함수 중 일부는 컴파일된 정규식의 모든 기능을 갖춘 메서드의 단순화된 버전입니다. 대부분의 사소하지 않은 응용 프로그램은 항상 컴파일된 형식을 사용합니다.
플래그¶
버전 3.6에서 변경: 플래그 상수는 이제 enum.IntFlag의 서브 클래스인 RegexFlag의 인스턴스입니다.
- class re.RegexFlag¶
아래에 나열된 정규식 옵션을 포함하는
enum.IntFlag클래스입니다.Added in version 3.11:
__all__\에 추가되었습니다.
- re.A¶
- re.ASCII¶
\w,\W,\b,\B,\d,\D,\s및\S\가 전체 유니코드 일치가 아닌 ASCII 전용 일치를 수행하도록 만듭니다. 이것은 유니코드 (str) 패턴에서만 의미가 있으며 bytes 패턴에서는 무시됩니다.인라인 플래그
(?a)에 해당합니다.
- re.DEBUG¶
컴파일된 표현식에 대한 디버그 정보를 표시합니다.
해당되는 인라인 플래그가 없습니다.
- re.I¶
- re.IGNORECASE¶
대소 문자를 구분하지 않는 일치를 수행합니다;
[A-Z]\와 같은 표현식은 소문자와도 일치할 것입니다.ASCII플래그를 사용하여 비 ASCII 일치를 비활성화하지 않는 한, 전체 유니코드 일치(예.:Ü가ü와 일치)도 작동합니다. 현재 로케일은LOCALE플래그가 사용되지 않으면 이 플래그의 효과를 변경하지 않습니다.인라인 플래그
(?i)에 해당합니다.유니코드 패턴
[a-z]\나[A-Z]가IGNORECASE플래그와 조합되어 사용될 경우, 52개의 ASCII 문자 및 4개의 추가 비 ASCII 문자(예.: ‘İ’(U+0130, 위에 점이 있는 라틴 대문자 I), ‘ı’(U+0131, 라틴 소문자 점 없는 i), ‘ſ’(U+017F, 라틴 소문자 긴 s) 및 ‘<0xE2><0x84><0xAA>’(U+212A, 켈빈 기호))와 일치합니다.ASCII플래그를 사용할 경우, ‘a’부터 ‘z’, 그리고 ‘A’부터 ‘Z’의 문자만 일치합니다.
- re.L¶
- re.LOCALE¶
\w,\W,\b,\B및 대소 문자를 구분하지 않는 일치가 유니코드 데이터베이스 대신 현재 로케일에 의존하도록 만듭니다. 이 플래그는 bytes 패턴에서만 사용할 수 있습니다.인라인 플래그
(?L)에 해당합니다.경고
이 플래그는 권장되지 않습니다. 대신 유니코드 일치를 고려해 보세요. 로케일 메커니즘은 한 번에 하나의 “문화”만 처리하고 8비트 로케일에서만 작동하여 매우 신뢰성이 떨어집니다. 유니코드 일치는 유니코드 (str) 패턴에서 기본적으로 활성화되며, 여러 로케일 및 언어를 처리할 수 있습니다.
버전 3.7에서 변경:
LOCALE플래그를 사용해 컴파일된 정규식 객체는 더 이상 컴파일 시간의 로케일에 의존하지 않습니다. 일치 시점의 로케일만이 일치 결과에 영향을 줍니다.
- re.M¶
- re.MULTILINE¶
지정된 경우, 패턴 문자
'^'는 문자열의 시작 부분과 각 라인의 시작 부분(각 줄 바꿈 바로 뒤)에서 일치하며; 패턴 문자'$'는 문자열의 끝 부분과 각 라인의 끝 부분(각 줄 바꿈 바로 앞)에서 일치합니다. 기본적으로,'^'만 문자열의 시작 부분에서 일치하고,'$'만 문자열의 끝 부분과 문자열 끝에 있는 개행 문자(있을 경우) 바로 앞에서 일치합니다.인라인 플래그
(?m)에 해당합니다.
- re.NOFLAG¶
플래그가 적용되지 않음을 나타내며, 값은
0입니다. 이 플래그는 함수 키워드 인자의 기본값 또는 다른 플래그와 조건부로 OR 연산될 기준값으로 사용될 수 있습니다. 기본값으로 사용하는 예시:def myfunc(pattern, text, flag=re.NOFLAG): return re.search(pattern, text, flag)
Added in version 3.11.
- re.S¶
- re.DOTALL¶
'.'특수 문자가 개행 문자를 포함하는 모든 문자와 일치하도록 만듭니다; 이 플래그가 없으면,'.'는 개행 문자를 제외한 모든 문자에 일치합니다.인라인 플래그
(?s)에 해당합니다.
- re.U¶
- re.UNICODE¶
Python 3에서는
str패턴에 대해 기본적으로 유니코드 문자가 일치합니다. 따라서 이 플래그는 효과 없음 으로 중복되며, 하위 호환성을 위해 유지됩니다.대신 ASCII 문자만 일치하도록 제한하려면 :py:const:`~re.ASCII`를 참조하세요.
- re.X¶
- re.VERBOSE¶
이 플래그는 패턴의 논리적 부분을 시각적으로 분리하고 주석을 추가하여 더 보기 좋고 가독성 높은 정규식을 작성할 수 있도록 합니다. 패턴 내의 공백은 문자 클래스 안에 있거나, 이스케이프되지 않은 백슬래시 앞에 있거나,
*?,(?:또는(?P<...>)와 같은 토큰 내에 있는 경우가 아니면 무시됩니다. 예를 들어,(? :및* ?는 허용되지 않습니다. 한 줄이 문자 클래스 안에 있지 않고 이스케이프 처리되지 않은 백슬래시로 시작하지 않는#을 포함하는 경우, 가장 왼쪽의 그러한#부터 해당 줄 끝까지 모든 문자는 무시됩니다.이것은 십진수와 일치하는 다음 두 정규식 객체는 기능적으로 같음을 뜻합니다:
a = re.compile(r"""\d + # 정수 부분 \. # 소수점 \d * # 임의의 분수 자리 숫자""") b = re.compile(r"\d+\.\d*")
인라인 플래그
(?x)에 해당합니다.
함수:¶
- re.compile(pattern, flags=0)¶
정규식 패턴을 정규식 객체\로 컴파일합니다. 정규식 객체는 아래에 설명되는
prefixmatch(),search()및 기타 메서드를 일치시키는 데 사용할 수 있습니다.패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.시퀀스
prog = re.compile(pattern) result = prog.search(string)
는 다음과 동등합니다
result = re.search(pattern, string)
하지만 정규식이 단일 프로그램에서 여러 번 사용될 때,
re.compile()을 사용하고 결과 정규식 객체를 저장하여 재사용하는 것이 더 효율적입니다.참고
re.compile()과 모듈 수준 일치 함수에 전달된 가장 최근 패턴의 컴파일된 버전이 캐시 되므로, 한 번에 몇 가지 정규식만 사용하는 프로그램은 정규식 컴파일에 대해 신경 쓸 필요가 없습니다.
- re.search(pattern, string, flags=0)¶
string 을 스캔하여 정규식 pattern 이 일치하는 첫 위치를 찾고 해당
Match를 반환합니다. 문자열의 어느 위치에서도 패턴과 일치하지 않으면None을 반환합니다. 참고로, 이는 문자열 내 특정 지점에서 길이가 없는 일치를 찾는 것과는 다릅니다.패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.
- re.prefixmatch(pattern, string, flags=0)¶
string 의 시작 부분에서 0개 이상의 문자가 정규식 pattern 과 일치하면 해당하는
Match를 반환합니다. 문자열이 패턴과 일치하지 않으면None을 반환합니다. 참고로, 이는 길이가 없는 일치와는 다릅니다.참고
MULTILINE모드에서도 이 함수는 문자열 시작 부분에서만 일치하며 각 라인의 시작 부분에서는 일치하지 않습니다.string의 모든 위치에서 일치를 찾으려면, 대신
search()를 사용하십시오 ([msgid] search() 대 prefixmatch()도 참조하십시오).패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.이 함수는 이제 두 개의 이름을 가지고 있으며 오랫동안 :func:`~re.match`으로 알려져 왔습니다. 이전 버전의 Python과의 호환성을 유지해야 할 때는 해당 이름을 사용하세요.
Added in version 3.15.
- re.match(pattern, string, flags=0)¶
버전 3.15부터 약하게 폐지 <Soft deprecated>:
match()has been soft deprecated in favor of the alternateprefixmatch()name of this API which is more explicitly descriptive. Use it to better express intent. The norm in other languages and regular expression implementations is to use the term match to refer to the behavior of what Python has always calledsearch(). See [msgid] prefixmatch() 대 match().
- re.fullmatch(pattern, string, flags=0)¶
만약 전체 string 이 정규식 pattern 과 일치하면 해당하는
Match를 반환합니다. 문자열이 패턴과 일치하지 않으면None을 반환합니다. 참고로, 이는 길이가 없는 일치와는 다릅니다.패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.Added in version 3.4.
- re.split(pattern, string, maxsplit=0, flags=0)¶
string을 pattern으로 나눕니다. pattern에서 포착하는 괄호가 사용되면 패턴의 모든 그룹 텍스트도 결과 리스트의 일부로 반환됩니다. maxsplit이 0이 아니면, 최대 maxsplit 분할이 발생하고, 나머지 문자열이 리스트의 마지막 요소로 반환됩니다.
>>> re.split(r'\W+', 'Words, words, words.') ['Words', 'words', 'words', ''] >>> re.split(r'(\W+)', 'Words, words, words.') ['Words', ', ', 'words', ', ', 'words', '.', ''] >>> re.split(r'\W+', 'Words, words, words.', maxsplit=1) ['Words', 'words, words.'] >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) ['0', '3', '9']
구분자에 포착하는 그룹이 있고 문자열 시작 부분에서 일치하면, 결과는 빈 문자열로 시작됩니다. 문자열의 끝에 대해서도 마찬가지입니다:
>>> re.split(r'(\W+)', '...words, words...') ['', '...', 'words', ', ', 'words', '...', '']
그런 식으로, 구분자 구성 요소는 항상 결과 리스트 내의 같은 상대 인덱스에서 발견됩니다.
연속된 빈 일치는 불가능하지만, 공백인 일치는 비어 있지 않은 일치 바로 다음에 발생할 수 있습니다.
>>> re.split(r'\b', 'Words, words, words.') ['', 'Words', ', ', 'words', ', ', 'words', '.'] >>> re.split(r'\W*', '...words...') ['', '', 'w', 'o', 'r', 'd', 's', '', ''] >>> re.split(r'(\W*)', '...words...') ['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']
패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.버전 3.1에서 변경: 선택적 flags 인자를 추가했습니다.
버전 3.7에서 변경: 빈 문자열과 일치 할 수 있는 패턴으로 분할하는 지원을 추가했습니다.
버전 3.13부터 폐지됨: :maxsplit 과 flags 를 위치 인자로 전달하는 것은 더 이상 사용되지 않습니다. 향후 Python 버전에서는 키워드 전용 가 될 것입니다.
- re.findall(pattern, string, flags=0)¶
string 에서 pattern 의 겹치지 않는 모든 일치를 문자열 또는 튜플 리스트로 반환합니다. string 은 왼쪽에서 오른쪽으로 스캔되며, 발견된 순서대로 일치가 반환됩니다. 빈 일치도 결과에 포함됩니다.
결과는 패턴의 캡처 그룹 개수에 따라 다릅니다. 그룹이 없으면 전체 패턴과 일치하는 문자열 리스트를 반환합니다. 정확히 하나의 그룹만 있으면 해당 그룹과 일치하는 문자열 리스트를 반환합니다. 여러 그룹이 있는 경우, 그룹과 일치하는 문자열의 튜플 리스트를 반환합니다. 비캡처 그룹은 결과 형태에 영향을 주지 않습니다.
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') ['foot', 'fell', 'fastest'] >>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10') [('width', '20'), ('height', '10')]
패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.버전 3.7에서 변경: 비어 있지 않은 일치는 이제 이전의 비어 있는 일치 직후에 시작할 수 있습니다.
- re.finditer(pattern, string, flags=0)¶
Return an iterator yielding
Matchobjects over all non-overlapping matches for the RE pattern in string. The string is scanned left-to-right, and matches are returned in the order found. Empty matches are included in the result.패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.버전 3.7에서 변경: 비어 있지 않은 일치는 이제 이전의 비어 있는 일치 직후에 시작할 수 있습니다.
- re.sub(pattern, repl, string, count=0, flags=0)¶
string에서 겹치지 않는 pattern의 가장 왼쪽 일치를 repl로 치환하여 얻은 문자열을 반환합니다. 패턴을 찾지 못하면, string이 변경되지 않고 반환됩니다. repl은 문자열이나 함수가 될 수 있습니다; 문자열이면 모든 역 슬래시 이스케이프가 처리됩니다. 즉,
\n은 단일 개행 문자로 변환되고,\r는 캐리지 리턴으로 변환되고, 등등. 알 수 없는 ASCII 글자 이스케이프는 나중에 사용하기 위해 예약되어 있으며 에러로 처리됩니다.\&와 같은 다른 알려지지 않은 이스케이프는 그대로 있습니다.\6과 같은 역참조는 패턴에서 그룹 6과 일치하는 부분 문자열로 치환됩니다. 예를 들면:>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):', ... r'static PyObject*\npy_\1(void)\n{', ... 'def myfunc():') 'static PyObject*\npy_myfunc(void)\n{'
만약 repl 가 함수라면, pattern 의 겹치지 않는 모든 발생마다 호출됩니다. 이 함수는 단일
Match인자를 받으며, 대체 문자열을 반환합니다. 예를 들면:>>> def dashrepl(matchobj): ... if matchobj.group(0) == '-': return ' ' ... else: return '-' ... >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 'pro--gram files' >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) 'Baked Beans & Spam'
패턴은 문자열 또는 :class:`~re.Pattern`일 수 있습니다.
선택적 인자 count 는 치환될 패턴 일치의 최대 개수입니다; count 는 음수가 아닌 정수여야 합니다. 생략되거나 0이면, 모든 발생이 치환됩니다.
인접한 빈 일치는 불가능하지만, 비어 있지 않은 일치 바로 뒤에 빈 일치가 발생할 수 있습니다. 결과적으로,
sub('x*', '-', 'abxd')``는 ``'-a-b--d-'``를 반환합니다 (이는 ``'-a-b-d-'대신입니다).문자열형 repl 인자에서, 위에 설명된 문자 이스케이프와 역참조 외에,
\g<name>는(?P<name>...)문법으로 정의한name이라는 그룹에 일치하는 부분 문자열을 사용합니다.\g<number>는 해당 그룹 번호를 사용합니다; 따라서\g<2>는\2와 동등하지만,\g<2>0와 같은 치환에서 모호하지 않습니다.\20은 그룹 2에 대한 참조에 리터럴 문자'0'이 뒤에 오는 것이 아니라, 그룹 20에 대한 참조로 해석됩니다. 역참조\g<0>은 RE와 일치하는 전체 부분 문자열을 치환합니다.패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.버전 3.1에서 변경: 선택적 flags 인자를 추가했습니다.
버전 3.5에서 변경: 일치하지 않는 그룹은 빈 문자열로 치환됩니다.
버전 3.6에서 변경: pattern의
'\'와 ASCII 글자(letter)로 구성된 알 수 없는 이스케이프는 이제 에러입니다.버전 3.7에서 변경: repl 내의
'\'와 ASCII 문자로 구성된 알 수 없는 이스케이프는 이제 에러입니다. 비어 있지 않은 일치 바로 뒤에 빈 일치가 발생할 수 있습니다.버전 3.12에서 변경: 그룹 id 에는 ASCII 숫자가 포함될 수 있습니다.
bytes대체 문자열에서는 그룹 name 이 ASCII 범위(b'\x00'-b'\x7f')의 바이트만 포함할 수 있습니다.버전 3.13부터 폐지됨: count 와 flags 를 위치 인자로 전달하는 것은 더 이상 권장되지 않습니다. 향후 Python 버전에서는 키워드 전용 가 될 것입니다.
- re.subn(pattern, repl, string, count=0, flags=0)¶
sub()와 같은 연산을 수행하지만, 튜플(new_string, number_of_subs_made)를 반환합니다.패턴의 동작은 flags 값을 지정하여 수정할 수 있습니다. 값은 비트별 OR(
|연산자)을 사용하여 결합된 flags 변수 중에서 사용할 수 있습니다.
- re.escape(pattern)¶
pattern에서 특수 문자를 이스케이프 처리합니다. 이것은 정규식 메타 문자가 포함되어있을 수 있는 임의의 리터럴 문자열을 일치시키려는 경우에 유용합니다. 예를 들면:
>>> print(re.escape('https://www.python.org')) https://www\.python\.org >>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:" >>> print('[%s]+' % re.escape(legal_chars)) [abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+ >>> operators = ['+', '-', '*', '/', '**'] >>> print('|'.join(map(re.escape, sorted(operators, reverse=True)))) /|\-|\+|\*\*|\*
이 함수는
sub()와subn()의 치환 문자열에 사용하면 안 되며, 역 슬래시만 이스케이프 해야 합니다. 예를 들면:>>> digits_re = r'\d+' >>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings' >>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample)) /usr/sbin/sendmail - \d+ errors, \d+ warnings
버전 3.3에서 변경:
'_'문자는 더는 이스케이프 되지 않습니다.버전 3.7에서 변경: 정규식에서 특별한 의미를 가질 수 있는 문자만 이스케이프 됩니다. 결과적으로,
'!','"','%',"'",',','/',':',';','<','=','>','@'및 ‘”'는 더는 이스케이프 되지 않습니다.
- re.purge()¶
정규식 캐시를 지웁니다.
예외¶
- exception re.PatternError(msg, pattern=None, pos=None)¶
여기 있는 함수에 전달된 문자열이 유효한 정규 표현식이 아니거나(예: 짝이 맞지 않는 괄호를 포함할 수 있음), 컴파일 또는 매칭 중 다른 오류가 발생하는 경우 발생합니다. 문자열이 패턴의 일치를 포함하지 않는다고 해서 오류는 아닙니다.
PatternError인스턴스는 다음 추가 속성을 가집니다:- msg¶
포맷되지 않은 에러 메시지.
- pattern¶
정규식 패턴.
- pos¶
컴파일이 실패한 위치를 가리키는 pattern의 인덱스 (
None일 수 있습니다).
- lineno¶
pos에 해당하는 줄 (
None일 수 있습니다).
- colno¶
pos에 해당하는 열 (
None일 수 있습니다).
버전 3.5에서 변경: 추가 어트리뷰트가 추가되었습니다.
정규 표현식 객체¶
- class re.Pattern¶
:func:`re.compile`에서 반환되는 컴파일된 정규 표현식 객체입니다.
패턴은 처리하는 문자열 유형에 대한 제네릭 <generics>`입니다 (:class:`str 또는
bytes).버전 3.9에서 변경:
re.Pattern는 유니코드(str) 또는 바이트 패턴을 표시하기 위해[]를 지원합니다. 제네릭 에일리어스 형 를 참조하십시오.
- Pattern.search(string[, pos[, endpos]])¶
string 을 스캔하여 이 정규 표현식이 일치를 생성하는 첫 번째 위치를 찾고, 해당
Match를 반환합니다. 문자열의 어느 위치에서도 패턴과 일치하지 않으면None을 반환합니다. 참고로 이것은 문자열 내의 특정 지점에서 널 길이 매칭(zero-length match)을 찾는 것과는 다릅니다.선택적 두 번째 매개 변수 pos는 검색을 시작할 문자열의 인덱스를 제공합니다; 기본값은
0입니다. 이것은 문자열을 슬라이싱하는 것과 완전히 동등하지는 않습니다;'^'패턴 문자는 문자열의 실제 시작 부분과 개행 직후의 위치에서 일치하지만, 검색을 시작할 색인에서 반드시 일치하지는 않습니다.선택적 매개 변수 endpos는 문자열을 어디까지 검색할지를 제한합니다; 문자열이 endpos 문자 길이인 것처럼 취급되어, 일치를 찾기 위해 pos에서
endpos - 1까지의 문자만 검색됩니다. endpos가 pos보다 작으면 일치는 없습니다; 그렇지 않으면, rx가 컴파일된 정규식 객체일 때,rx.search(string, 0, 50)는rx.search(string[:50], 0)와 동등합니다.>>> pattern = re.compile("d") >>> pattern.search("dog") # Match at index 0 <re.Match object; span=(0, 1), match='d'> >>> pattern.search("dog", 1) # No match; search doesn't include the "d"
- Pattern.prefixmatch(string[, pos[, endpos]])¶
string 의 시작점}에서 0개 이상의 문자가 이 정규 표현식과 일치하면, 해당
Match를 반환합니다. 문자열이 패턴과 일치하지 않으면None을 반환합니다. 참고로 이것은 널 길이 매칭과는 다릅니다.Note that even in
MULTILINEmode, this will only match at the beginning of the string and not at the beginning of each line.선택적 pos와 endpos 매개 변수는
search()메서드에서와 같은 의미입니다.>>> pattern = re.compile("o") >>> pattern.prefixmatch("dog") # No match as "o" is not at the start of "dog". >>> pattern.prefixmatch("dog", 1) # Match as "o" is the 2nd character of "dog". <re.Match object; span=(1, 2), match='o'>
string의 임의 위치에서 일치를 찾으려면, 대신
search()를 사용하십시오 ([msgid] search() 대 prefixmatch()도 참조하십시오).이 메서드는 이제 두 개의 이름으로 존재하며 오랫동안 :meth:`~Pattern.match`로 알려져 왔습니다. 이전 Python 버전과의 호환성을 유지해야 할 때는 해당 이름을 사용하십시오.
Added in version 3.15.
- Pattern.match(string[, pos[, endpos]])¶
버전 3.15부터 약하게 폐지 <Soft deprecated>:
match()has been soft deprecated in favor of the alternateprefixmatch()name of this API which is more explicitly descriptive. Use it to better express intent. The norm in other languages and regular expression implementations is to use the term match to refer to the behavior of what Python has always calledsearch(). See [msgid] prefixmatch() 대 match().
- Pattern.fullmatch(string[, pos[, endpos]])¶
전체 string 이 이 정규 표현식과 일치하면, 해당
Match를 반환합니다. 문자열이 패턴과 일치하지 않으면None을 반환합니다. 참고로 이것은 0 길이 일치와는 다릅니다.선택적 pos와 endpos 매개 변수는
search()메서드에서와 같은 의미입니다.>>> pattern = re.compile("o[gh]") >>> pattern.fullmatch("dog") # "o"가 "dog"의 시작 부분이 아니므로 일치하지 않음. >>> pattern.fullmatch("ogre") # 전체 문자열이 일치하지 않아 일치하지 않음. >>> pattern.fullmatch("doggie", 1, 3) # 주어진 범위 내에서 일치함. <re.Match object; span=(1, 3), match='og'>
Added in version 3.4.
- Pattern.findall(string[, pos[, endpos]])¶
findall()함수와 유사한데, 컴파일된 패턴을 사용합니다. 하지만,search()처럼 검색 영역을 제한하는 선택적 pos와 endpos 매개 변수도 받아들입니다.
- Pattern.finditer(string[, pos[, endpos]])¶
finditer()함수와 유사한데, 컴파일된 패턴을 사용합니다. 하지만,search()처럼 검색 영역을 제한하는 선택적 pos와 endpos 매개 변수도 받아들입니다.
- Pattern.flags¶
The regex matching flags. This is a combination of the flags given to
compile(), any(?...)inline flags in the pattern, and implicit flags such asUNICODEif the pattern is a Unicode string.
- Pattern.groups¶
패턴에 있는 포착 그룹 수.
- Pattern.groupindex¶
(?P<id>)로 정의된 기호 그룹 이름을 그룹 번호에 매핑하는 딕셔너리. 패턴에 기호 그룹이 사용되지 않으면 딕셔너리는 비어 있습니다.
- Pattern.pattern¶
패턴 객체가 컴파일된 패턴 문자열.
버전 3.7에서 변경: copy.copy()와 copy.deepcopy() 지원이 추가되었습니다. 컴파일된 정규식 객체는 원자적이라고 간주합니다.
Match 객체¶
일치 객체는 항상 불리언 값 True를 가집니다. match()와 search()는 일치가 없을 때 None을 반환하기 때문에, 간단한 if 문으로 일치가 있는지 검사할 수 있습니다:
if match := re.search(pattern, string):
process(match)
- class re.Match¶
성공적인
match나search를 통해 반환된 Match 객체입니다.일치는 일치한 문자열의 타입에 대한 generic <generics>`입니다 ( :class:`str 또는
bytes).버전 3.9에서 변경:
re.Match는 Unicode(str) 또는 bytes 일치를 나타내는[]를 지원합니다. 제네릭 에일리어스 형 를 참고하십시오.
- Match.expand(template)¶
sub()메서드에 의해 수행된 템플릿 문자 template 의 백슬래시 치환을 통해 얻은 문자열을 반환합니다.\n과 같은 이스케이프는 적절한 문자로 변환되며, 숫자 백레퍼런스 (\1,\2)와 이름 지정된 백레퍼런스 (\g<1>, ` g<name>`)는 해당 그룹의 내용으로 대체됩니다. 백레퍼런스 ` g<0>``은 전체 일치 문자열로 대체됩니다.버전 3.5에서 변경: 일치하지 않는 그룹은 빈 문자열로 치환됩니다.
- Match.group([group1, ...])¶
일치의 하나 이상의 서브 그룹을 반환합니다. 단일 인자가 있으면, 결과는 단일 문자열입니다; 인자가 여러 개면, 결과는 인자당 하나의 항목이 있는 튜플입니다. 인자가 없으면, group1 의 기본값은 0입니다 (전체 일치가 반환됩니다). groupN 인자가 0이면, 해당 반환 값은 전체 일치 문자열이며; 양의 정수이면, 해당 괄호로 묶인 그룹과 일치하는 문자열입니다. 그룹 번호가 음수이거나 패턴에 정의된 그룹 수보다 크면,
IndexError예외가 발생합니다. 그룹이 패턴의 일부에서 일치하지 않은 부분에 포함되어 있으면, 해당 결과는None입니다. 그룹이 여러 번 일치하는 패턴의 일부에 포함되어 있으면, 마지막 일치가 반환됩니다.>>> m = re.search(r"\A(\w+) (\w+)", "Norwegian Blue, pining for the fjords") >>> m.group(0) # 전체 일치 'Norwegian Blue' >>> m.group(1) # 첫 번째 괄호 그룹. 'Norwegian' >>> m.group(2) # 두 번째 괄호 그룹. 'Blue' >>> m.group(1, 2) # 여러 인자는 튜플을 제공합니다. ('Norwegian', 'Blue')
정규식이
(?P<name>...)문법을 사용하면, groupN 인자는 그룹 이름으로 그룹을 식별하는 문자열일 수도 있습니다. 문자열 인자가 패턴의 그룹 이름으로 사용되지 않으면,IndexError예외가 발생합니다.적당히 복잡한 예:
>>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit") >>> m.group('adjective') 'killer' >>> m.group('animal') 'rabbit'
이름있는 그룹은 인덱스로 참조할 수도 있습니다:
>>> m.group(1) 'killer' >>> m.group(2) 'rabbit'
그룹이 여러 번 일치하면, 마지막 일치만 액세스 할 수 있습니다:
>>> m = re.search(r"(..)+", "a1b2c3") # 세 번 일치함. >>> m.group(1) # 가장 최근의 일치만 반환합니다. 'c3'
- Match.__getitem__(g)¶
이것은
m.group(g)와 같습니다. 일치에서 개별 그룹에 더 쉽게 액세스 할 수 있게 합니다:>>> m = re.search(r"(\w+) (\w+)", "Norwegian Blue, pining for the fjords") >>> m[0] # 전체 일치 'Norwegian Blue' >>> m[1] # 첫 번째 괄호 그룹. 'Norwegian' >>> m[2] # 두 번째 괄호 그룹. 'Blue'
이름 지정된 그룹도 지원됩니다:
>>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit") >>> m['adjective'] 'killer' >>> m['animal'] 'rabbit'
Added in version 3.6.
- Match.groups(default=None)¶
1에서 패턴에 있는 그룹의 수까지, 일치의 모든 서브 그룹을 포함하는 튜플을 반환합니다. default 인자는 일치에 참여하지 않은 그룹에 사용됩니다; 기본값은
None입니다.예를 들면:
>>> m = re.search(r"(\d+)\.(\d+)", "24.1632") >>> m.groups() ('24', '1632')
우리가 소수점과 그 이후의 모든 것을 선택적으로 만들면, 모든 그룹이 일치에 참여하지 않을 수 있습니다. 이 그룹은 default 인자가 주어지지 않는 한 기본값
None이 됩니다:>>> m = re.search(r"(\d+)\.?(\d+)?", "24") >>> m.groups() # 두 번째 그룹은 기본적으로 None입니다. ('24', None) >>> m.groups('0') # 이제 두 번째 그룹의 기본값은 '0'입니다. ('24', '0')
- Match.groupdict(default=None)¶
일치의 모든 이름 있는 서브 그룹을 포함하고, 서브 그룹의 이름을 키로 사용하는 딕셔너리를 반환합니다. default 인자는 일치에 참여하지 않은 그룹에 사용됩니다; 기본값은
None입니다. 예를 들면:>>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit") >>> m.groupdict() {'adjective': 'killer', 'animal': 'rabbit'}
- Match.start([group])¶
- Match.end([group])¶
group과 일치하는 부분 문자열의 시작과 끝 인덱스를 반환합니다; group의 기본값은 0입니다 (전체 일치 문자열을 뜻합니다). group이 있지만, 일치에 기여하지 않으면,
-1을 반환합니다. 일치 객체 m과 일치에 기여한 그룹 g에서, 그룹 g와 일치하는 부분 문자열(m.group(g)와 동등합니다)은 다음과 같습니다m.string[m.start(g):m.end(g)]
group이 널 문자열과 일치하면
m.start(group)은m.end(group)와 같음에 유의하십시오. 예를 들어,m = re.search('b(c?)', 'cba')이후에,m.start(0)은 1이고,m.end(0)은 2이며,m.start(1)과m.end(1)은 모두 2이고,m.start(2)는IndexError예외를 발생시킵니다.전자 메일 주소에서 remove_this를 제거하는 예:
>>> email = "tony@tiremove_thisger.net" >>> m = re.search("remove_this", email) >>> email[:m.start()] + email[m.end():] 'tony@tiger.net'
- Match.span([group])¶
일치가 m일 때, 2-튜플
(m.start(group), m.end(group))를 반환합니다. group이 일치에 기여하지 않으면, 이것은(-1, -1)임에 유의하십시오. group의 기본값은 0으로, 전체 일치입니다.
- Match.lastindex¶
마지막으로 일치하는 포착 그룹의 정수 인덱스, 또는 그룹이 전혀 일치하지 않으면
None. 예를 들어, 정규식(a)b,((a)(b))및((ab))는 문자열'ab'에 적용될 경우lastindex == 1이 되지만,(a)(b)정규식은 같은 문자열에 적용될 때lastindex == 2가 됩니다.
- Match.lastgroup¶
마지막으로 일치하는 포착 그룹의 이름, 또는 그룹에 이름이 없거나, 그룹이 전혀 일치하지 않으면
None.
버전 3.7에서 변경: copy.copy()와 copy.deepcopy() 지원이 추가되었습니다. 일치 객체는 원자적이라고 간주합니다.
정규 표현식 예제¶
쌍 검사하기¶
이 예제에서는, 다음과 같은 도우미 함수를 사용하여 좀 더 세련되게 일치 객체를 표시합니다:
def displaymatch(match):
if match is None:
return None
return '<Match: %r, groups=%r>' % (match.group(), match.groups())
플레이어의 패를 5문자 문자열로 나타내는 포커 프로그램을 작성하고 있다고 가정해봅시다. “a”는 에이스, “k”는 킹, “q”는 퀸, “j”는 잭, “t”는 10, “2”에서 “9”는 그 값의 카드를 나타냅니다.
주어진 문자열이 유효한 패인지 보려면, 다음과 같이 할 수 있습니다:
>>> valid_hand\_re = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid_hand\_re.search("akt5q")) # 유효함.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid_hand\_re.search("akt5e")) # 유효하지 않음.
>>> displaymatch(valid_hand\_re.search("akt")) # 유효하지 않음.
>>> displaymatch(valid_hand\_re.search("727ak")) # 유효함.
"<Match: '727ak', groups=()>"
마지막 패 "727ak"는 페어, 즉 같은 값의 카드 두 장을 포함합니다. 이것을 정규식과 일치시키려면, 역참조를 다음과 같이 사용할 수 있습니다:
>>> pair_re = re.compile(r".*(.).*\1")
>>> displaymatch(pair_re.prefixmatch("717ak")) # 7쌍을 찾았습니다.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair_re.prefixmatch("718ak")) # 쌍이 없습니다.
>>> displaymatch(pair_re.prefixmatch("354aa")) # 에이스 쌍을 찾았습니다.
"<Match: '354aa', groups=('a',)>"
페어가 어떤 카드로 구성되어 있는지 알아내려면, 다음과 같이 일치 객체의 group() 메서드를 사용할 수 있습니다:
>>> pair_re = re.compile(r".*(.).*\1")
>>> pair_re.prefixmatch("717ak").group(1)
'7'
# Error because prefixmatch()은 None을 반환하며, 이 값은 group() 메서드를 가지고 있지 않습니다:
>>> pair_re.prefixmatch("718ak").group(1)
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
pair_re.prefixmatch("718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'
>>> pair_re.prefixmatch("354aa").group(1)
'a'
scanf() 시뮬레이션¶
Python에는 현재 scanf`에 해당하는 기능이 없습니다. 정규식은 일반적으로 :c:func:()!scanf` 형식 문자열보다 더 강력하지만, 더 장황합니다. 다음 표에서는 scanf() 형식 토큰과 정규 표현식 간의 유사한 매핑을 제공합니다.
[msgid]
|
정규식 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[msgid] 문자열 예시로부터 파일명과 숫자를 추출하려면 다음과 같이 합니다:
[msgid]
/usr/sbin/sendmail - 0 errors, 4 warnings
[msgid]
다음과 같은 scanf() 형식을 사용합니다:
[msgid]
%s - %d errors, %d warnings
[msgid] 이와 동등한 정규식은 다음과 같습니다:
[msgid]
(\S+) - (\d+) errors, (\d+) warnings
[msgid] search() 대 prefixmatch()¶
[msgid] Python은 정규식에 기반한 여러 기본 연산을 제공합니다:
[msgid] :func:`re.prefixmatch`는 문자열의 시작 부분에서만 일치 여부를 확인합니다
[msgid] :func:`re.search`는 문자열 어느 곳에서나 일치하는지를 검사합니다 (이것이 Perl의 기본 동작입니다)
[msgid] :func:`re.fullmatch`는 전체 문자열이 일치하는지 확인합니다
예를 들면:
[msgid]
>>> re.prefixmatch("c", "abcdef") # 일치 없음
>>> re.search("c", "abcdef") # 일치함
<re.Match object; span=(2, 3), match='c'>
>>> re.fullmatch("p.*n", "python") # 일치함
<re.Match object; span=(0, 6), match='python'>
>>> re.fullmatch("r.*n", "python") # 일치 없음
'^'로 시작하는 정규식은 search()와 함께 사용하여 문자열 시작 부분의 일치로 제한 할 수 있습니다:
[msgid]
>>> re.prefixmatch("c", "abcdef") # 일치 없음
>>> re.search("^c", "abcdef") # 일치 없음
>>> re.search("^a", "abcdef") # 일치함
<re.Match object; span=(0, 1), match='a'>
[msgid]
하지만 MULTILINE 모드에서는 :func:`prefixmatch`가 문자열 시작 부분에서만 일치하는 반면, 정규식을 사용하여 `^`로 시작하는 경우 :func:`search`는 각 줄의 시작 부분에서 일치합니다.
[msgid]
>>> re.prefixmatch("X", "A\nB\nX", re.MULTILINE) # 일치 없음
>>> re.search("^X", "A\nB\nX", re.MULTILINE) # 일치함
<re.Match object; span=(4, 5), match='X'>
[msgid] prefixmatch() 대 match()¶
[msgid]
match() 함수와 메서드는 왜 더 긴 prefixmatch() 철자 대신 사용이 권장되지 않을까요?
[msgid]
파이썬에 정규식이 추가된 이후 다른 많은 언어도 정규식 지원 라이브러리를 갖추게 되었습니다. 그러나 가장 인기 있는 언어에서도 그들은 search() 가 파이썬에서 제공하는 앵커되지 않은 동작을 의미하기 위해 API에서 match 라는 용어를 사용합니다. 따라서 match 라는 일반적인 용어의 사용은 다른 언어에 익숙한 사용자에게 모호할 수 있습니다. 그들은 직관적으로 인식되는 업계 규범과 파이썬 API가 다르게 작동하는 것에 익숙하지 않기 때문입니다.
[msgid]
Python의 Zen Of Python (python3 -m this)에서 인용된 것처럼: “명시적인 것이 암시적인 것보다 낫습니다”. prefixmatch`라는 이름을 읽는 사람이라면 의도된 의미를 이해할 가능성이 높습니다. :func:()!match`를 읽을 때, 이 오래된 파이썬의 함정에는 아직 의도된 동작에 대한 의구심이 남아있습니다.
[msgid]
저희는 예전부터 코드에서 사용되어 온 match`라는 이름을 제거할 계획은 없습니다. 30년 이상 사용되었습니다. 이는 :term:`soft deprecated(): 지원하는 이전 버전의 Python 코드는 계속해서 match`를 사용해야 하며, 새 코드는 :func:()!prefixmatch`를 선호해야 합니다.
Added in version 3.15: prefixmatch()
버전 3.15부터 약하게 폐지 <Soft deprecated>: match()
[msgid] 전화번호부 만들기¶
split()는 문자열을, 전달된 패턴으로 구분된 리스트로 분할합니다. 이 메서드는 전화번호부를 만드는 다음 예제에서 보이듯이 텍스트 데이터를 파이썬에서 쉽게 읽고 수정할 수 있는 데이터 구조로 변환하는 데 매우 중요합니다.
먼저, 여기 입력이 있습니다. 보통 파일에서 올 수 있습니다만, 여기서는 삼중 따옴표로 묶인 문자열 문법을 사용합니다.
>>> text = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""
항목은 하나 이상의 개행으로 구분됩니다. 이제 비어있지 않은 각 줄이 항목이 되도록 문자열을 리스트로 변환합니다:
>>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']
마지막으로, 각 항목을 이름, 성, 전화번호 및 주소로 구성된 리스트로 분할합니다. 주소에 우리의 분할 패턴인 스페이스가 들어있기 때문에, split()의 maxsplit 매개 변수를 사용합니다:
>>> [re.split(":? ", entry, maxsplit=3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
:? 패턴은 결과 리스트에 나타나지 않도록, 성 뒤의 콜론과 일치합니다. maxsplit로 4를 사용하면, 번지수를 거리 이름과 분리 할 수 있습니다:
>>> [re.split(":? ", entry, maxsplit=4) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
[msgid] 텍스트 다듬기 (Text Munging)¶
sub()는 패턴의 모든 일치를 문자열이나 함수의 결과로 치환합니다. 이 예제는 sub()에 텍스트를 “뒤섞는”, 즉 문장의 각 단어에서 첫 번째 문자와 마지막 문자를 제외한 모든 문자의 순서를 무작위로 바꾸는 함수를 사용하는 방법을 보여줍니다:
>>> def repl(m):
... inner_word = list(m.group(2))
... random.shuffle(inner_word)
... return m.group(1) + "".join(inner_word) + m.group(3)
...
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
[msgid] 모든 부사 찾기¶
findall()은 search()처럼 첫 번째 등장뿐만 아니라, 패턴의 모든 등장과 일치합니다. 예를 들어, 작가가 어떤 텍스트에서 부사를 모두 찾고 싶으면, 다음과 같은 방식으로 findall()을 사용할 수 있습니다:
>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly\b", text)
['carefully', 'quickly']
모든 부사와 그 위치 찾기¶
패턴의 모든 일치 항목에 대해 일치한 텍스트 외의 더 많은 정보가 필요한 경우, finditer`를 사용하면 문자열 대신 :class:`~re.Match() 객체를 제공하므로 유용합니다. 이전 예시를 계속하자면, 작가가 어떤 텍스트에서 부사 와 그 위치 모두를 찾고 싶다면, 다음과 같은 방식으로 :func:`finditer`를 사용할 수 있습니다:
>>> text = "He was carefully disguised but captured quickly by police."
>>> for m in re.finditer(r"\w+ly\b", text):
... print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))
07-16: carefully
40-47: quickly
날 문자열 표기법¶
날 문자열 표기법(r"text")은 정규식을 합리적인 상태로 유지합니다. 이것 없이는, 정규식의 모든 역 슬래시('\')를 이스케이프 하기 위해 그 앞에 또 하나의 역 슬래시를 붙여야 합니다. 예를 들어, 다음 두 코드 줄은 기능상으로 같습니다:
>>> re.search(r"\W(.)\1\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
>>> re.search("\\W(.)\\1\\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
리터럴 역 슬래시와 일치시키려면, 정규식에서 이스케이프 되어야 합니다. 날 문자열 표기법을 사용하면, r"\\"이 됩니다. 날 문자열 표기법을 사용하지 않으면, "\\\\"를 사용해야 하는데, 다음 코드 줄들은 기능적으로 같습니다:
>>> re.search(r"\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
>>> re.search("\\\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
토크나이저 작성하기¶
토크나이저나 스캐너는 문자열을 분석하여 문자 그룹을 분류합니다. 이것은 컴파일러나 인터프리터를 작성하는 데 유용한 첫 번째 단계입니다.
텍스트 범주는 정규식으로 지정됩니다. 이 기법은 이들을 하나의 마스터 정규식으로 결합하고 연속적인 일치를 반복하는 것입니다:
from typing import NamedTuple
import re
class Token(NamedTuple):
type: str
value: int | float | str
line: int
column: int
def tokenize(code):
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
token_specification = [
('NUMBER', r'\d+(\.\d*)?'), # 정수 또는 소수점 숫자
('ASSIGN', r':='), # 할당 연산자
('END', r';'), # 구문 종결자
('ID', r'[A-Za-z]+'), # 식별자
('OP', r'[+\-*/]'), # 산술 연산자
('NEWLINE', r'\n'), # 줄 바꿈 문자
('SKIP', r'[ \t]+'), # 공백과 탭 무시
('MISMATCH', r'.'), # 다른 모든 문자
]
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
line_num = 1
line_start = 0
for mo in re.finditer(tok_regex, code):
kind = mo.lastgroup
value = mo.group()
column = mo.start() - line_start
if kind == 'NUMBER':
value = float(value) if '.' in value else int(value)
elif kind == 'ID' and value in keywords:
kind = value
elif kind == 'NEWLINE':
line_start = mo.end()
line_num += 1
continue
elif kind == 'SKIP':
continue
elif kind == 'MISMATCH':
raise RuntimeError(f'{value!r} unexpected on line {line_num}')
yield Token(kind, value, line_num, column)
statements = '''
IF quantity THEN
total := total + price * quantity;
tax := price * 0.05;
ENDIF;
'''
for token in tokenize(statements):
print(token)
토크나이저는 다음과 같은 출력을 생성합니다:
Token(type='IF', value='IF', line=2, column=4)
Token(type='ID', value='quantity', line=2, column=7)
Token(type='THEN', value='THEN', line=2, column=16)
Token(type='ID', value='total', line=3, column=8)
Token(type='ASSIGN', value=':=', line=3, column=14)
Token(type='ID', value='total', line=3, column=17)
Token(type='OP', value='+', line=3, column=23)
Token(type='ID', value='price', line=3, column=25)
Token(type='OP', value='*', line=3, column=31)
Token(type='ID', value='quantity', line=3, column=33)
Token(type='END', value=';', line=3, column=41)
Token(type='ID', value='tax', line=4, column=8)
Token(type='ASSIGN', value=':=', line=4, column=12)
Token(type='ID', value='price', line=4, column=15)
Token(type='OP', value='*', line=4, column=21)
Token(type='NUMBER', value=0.05, line=4, column=23)
Token(type='END', value=';', line=4, column=27)
Token(type='ENDIF', value='ENDIF', line=5, column=4)
Token(type='END', value=';', line=5, column=9)
Friedl, Jeffrey. Mastering Regular Expressions. 3rd ed., O’Reilly Media, 2009. 이 책의 세 번째 판은 더는 파이썬을 다루지 않지만, 초판은 훌륭한 정규식 패턴 작성을 아주 자세하게 다루었습니다.