>  기사  >  백엔드 개발  >  Python 정규식 작업에 대한 자세한 가이드

Python 정규식 작업에 대한 자세한 가이드

巴扎黑
巴扎黑원래의
2017-05-21 11:16:381665검색

Python은 버전 1.5부터 Perl 스타일 정규식 패턴을 제공하는 re 모듈을 추가했습니다. Python 1.5 이전 버전에서는 regex 모듈을 통해 Emecs 스타일 패턴을 제공했습니다. Emacs 스타일 모드는 약간 덜 읽기 쉽고 덜 강력하므로 새 코드를 작성할 때 regex 모듈을 사용하지 마십시오. 물론 때때로 이전 코드에서 여전히 그 흔적을 찾을 수 있습니다.

특성상 정규식(또는 RE)은 Python에 내장되고 re 모듈을 통해 구현되는 작고 고도로 전문화된 프로그래밍 언어입니다. 이 작은 언어를 사용하면 일치시키려는 해당 문자열 집합에 대한 규칙을 지정할 수 있습니다. 해당 문자열 집합에는 영어 문장, 전자 메일 주소, TeX 명령 또는 원하는 모든 것이 포함될 수 있습니다. 그런 다음 "이 문자열이 패턴과 일치합니까?" 또는 "이 문자열의 일부가 패턴과 일치합니까?"와 같은 질문을 할 수 있습니다. RE를 사용하여 다양한 방법으로 문자열을 수정하거나 분할할 수도 있습니다.


정규 표현식 패턴은 일련의 바이트코드로 컴파일된 후 C로 작성된 일치 엔진에 의해 실행됩니다. 고급 사용법에서는 엔진이 주어진 RE를 실행하는 방법과 생성된 바이트코드를 더 빠르게 실행하기 위해 RE가 특정 방식으로 작성되는 방법에 세심한 주의를 기울이고 싶을 수도 있습니다. 최적화를 위해서는 일치 엔진의 내부 메커니즘을 완전히 이해해야 하므로 이 문서에서는 최적화를 다루지 않습니다.


정규식 언어는 비교적 작고 제한적(제한된 기능)이므로 정규식으로 모든 문자열 처리를 수행할 수는 없습니다. 물론 정규식으로 수행할 수 있는 작업도 있지만 결국에는 표현식이 매우 복잡해집니다. 이러한 상황이 발생하면 이를 처리하기 위해 Python 코드를 작성하는 것이 더 나을 수 있습니다. Python 코드는 멋진 정규식보다 느리지만 이해하기는 더 쉽습니다.

간단 모드

가장 간단한 정규식 학습부터 시작하겠습니다. 정규식은 문자열 조작에 자주 사용되므로 가장 일반적인 작업인 문자 일치부터 시작하겠습니다.


정규식(결정론적 및 비결정론적 유한 오토마타)의 기반이 되는 컴퓨터 과학에 대한 자세한 설명을 보려면 컴파일러 작성에 관한 교과서를 참조하세요.

문자 매칭

대부분의 문자와 문자는 일반적으로 서로 일치합니다. 예를 들어 정규식 테스트는 "test"라는 문자열과 정확히 일치합니다. (이 RE를 "Test" 또는 "TEST"와 일치시키는 대소문자 구분 모드를 사용할 수도 있습니다. 자세한 내용은 나중에 설명합니다.)

물론 이 규칙에는 다소 특수한 문자도 있습니다. , 그들은 스스로 일치하지 않지만 특별한 것과 일치해야 함을 나타냅니다. 그렇지 않으면 RE의 다른 부분의 반복 횟수에 영향을 미칩니다. 이 기사의 많은 부분은 다양한 메타문자와 그 기능을 논의하는 데 할애되었습니다.

다음은 메타 문자의 전체 목록입니다. 해당 의미는 이 가이드의 나머지 부분에서 논의됩니다.

. ^ $ * + ? { [ ] | ( )

먼저 살펴보는 메타문자는 "[" 및 "]"입니다. 일치시키려는 문자 세트인 문자 범주를 지정하는 데 자주 사용됩니다. 문자를 개별적으로 나열할 수도 있고, "-" 기호로 구분된 두 개의 지정된 문자를 사용하여 문자 범위를 나타낼 수도 있습니다. 예를 들어, [abc]는 "a", "b" 또는 "c" 사이의 모든 문자와 일치합니다. 간격 [a-c]를 사용하여 이전과 동일한 효과를 갖는 동일한 문자 집합을 나타낼 수도 있습니다. 소문자만 일치시키려면 RE를 [a-z]로 작성해야 합니다.

메타 문자는 카테고리에서 작동하지 않습니다. 예를 들어, [akm$]는 "a", "k", "m" 또는 "$" 문자와 일치합니다. "$"는 일반적으로 메타 문자로 사용되지만 문자 클래스 내에서는 해당 특성이 제거됩니다. , 일반 문자로 되돌립니다.

보어를 사용하여 범위에 없는 문자를 일치시킬 수 있습니다. 방법은 "^"를 범주의 첫 번째 문자로 사용하는 것입니다. 다른 곳에서는 "^"가 단순히 "^" 문자 자체와 일치합니다. 예를 들어, [^5]는 "5"를 제외한 모든 문자와 일치합니다.

아마도 가장 중요한 메타 문자는 백슬래시 """일 것입니다. Python의 문자열 문자로서 백슬래시 뒤에 다른 문자를 추가하여 다양한 특수 의미를 표현할 수 있습니다. 또한 모든 메타 문자를 취소하는 데 사용할 수도 있습니다. 예를 들어 "[" 또는 """ 문자를 일치시켜야 하는 경우 문자 앞에 백슬래시를 추가하여 "[ 또는 " "와 같은 특별한 의미를 제거할 수 있습니다.

숫자, 문자 또는 기타 비어 있지 않은 문자 세트와 같이 """로 시작하는 특수 문자로 표시되는 일부 미리 정의된 문자 세트는 일반적으로 유용합니다. 다음은 사용 가능한 사전 설정 특수 문자입니다.

# !python

>>> 가져오기 re

>>> p = re.compile( 'ab*')

>>> 인쇄p

<re.RegexObject 인스턴스(80b4150>

re.compile()은 다양한 특수 기능 및 구문 변경을 구현하는 데 자주 사용되는 선택적 플래그 매개변수도 허용합니다. 나중에 사용 가능한 모든 설정을 살펴보겠지만 지금은 한 가지 예만 살펴보겠습니다.


#!python

>> ; > p = re.compile('ab*', re.IGNORECASE)

RE는 re.compile()에 문자열로 전송됩니다. RE는 정규식이 Python 언어의 핵심 부분이 아니고 이에 대한 특정 구문이 생성되지 않았기 때문에 문자열로 처리됩니다. (응용 프로그램에는 단순히 RE가 필요하지 않으므로 RE를 포함하여 언어 사양을 부풀릴 필요가 없습니다.) re 모듈은 소켓이나 zlib 모듈과 마찬가지로 Python에 C 확장 모듈로 포함됩니다.


Python 언어의 단순성을 보장하기 위해 RE를 문자열로 사용하지만 이는 다음 섹션의 제목에서 언급한 것처럼 문제를 야기합니다.

백슬래시 문제

이전 규정에서는 정규식에서 백슬래시 문자(""")를 사용하여 특수 서식을 나타내거나 특수 사용법을 호출하지 않고도 특수 문자의 사용을 허용했습니다. Python에서는 문자열에 동일한 문자를 사용합니다.


문자열 ""section"과 일치하는 RE를 작성하려고 한다고 가정해 보겠습니다. 아마도 LATEX 파일을 찾고 있을 것입니다. 프로그램 코드로 판단하려면 먼저 일치시키려는 문자열을 작성하세요. 다음으로 모든 백슬래시와 메타문자 앞에 백슬래시를 붙여서 특별한 의미를 제거해야 합니다.

字符 阶段
section 要匹配的字符串
\section 为 re.compile 取消反斜杠的特殊意义
"\section" 为字符串取消反斜杠


간단히 말하면, 백슬래시를 일치시키려면 RE 문자열에 '\'를 써야 합니다. 왜냐하면 정규식은 "\"여야 하고 모든 백슬래시 막대는 다음과 같아야 하기 때문입니다. Python 문자열 문자 표현 규칙에 따라 "\"로 표시됩니다. RE에서 백슬래시의 반복적인 특성으로 인해 많은 수의 백슬래시가 반복되어 결과 문자열을 이해하기 어렵습니다.


해결책은 정규 표현식에 Python의 원시 문자열 표현을 사용하는 것입니다. 문자열이 특별한 방법으로 처리되지 않기 전에 "r" 백슬래시를 추가하면 r"n "은 "를 포함하는 두 문자입니다. " 및 "n", 그리고 "n"은 개행을 나타내는 하나의 문자입니다. 정규식은 일반적으로 Python 코드에서 이 원시 문자열로 표시됩니다.

常规字符串 Raw 字符串
"ab*" r"ab*"
"\section" r"\section"
"\w+\s+" r"w+s+1"

일치 수행

컴파일된 정규식 개체가 있으면 어떻게 합니까? `RegexObject` 인스턴스에는 몇 가지 메서드와 속성이 있습니다. 여기에는 가장 중요한 항목만 표시됩니다. 전체 목록을 보려면 Python 라이브러리 참조

方法/属性 作用
match() 决定 RE 是否在字符串刚开始的位置匹配
search() 扫描字符串,找到这个 RE 匹配的位置
findall() 找到 RE 匹配的所有子串,并把它们作为一个列表返回
finditer() 找到 RE 匹配的所有子串,并把它们作为一个迭代器返回
를 참조하세요.


일치하는 항목이 없으면 match() 및 search()는 None을 반환합니다. 성공하면 일치 항목에 대한 정보(시작 및 종료 위치, 일치하는 하위 문자열 등)가 포함된 'MatchObject' 인스턴스가 반환됩니다.

인간-기계 대화를 사용하고 re 모듈을 실험하면서 배울 수 있습니다. Tkinter가 있다면 Python 배포판에 포함된 데모 프로그램인 Tools/scripts/redemo.py를 살펴보는 것이 좋습니다.

먼저 Python 인터프리터를 실행하고 re 모듈을 가져온 후 RE를 컴파일합니다.

#!python

Python
2.2.2 (#1, 2003년 2월 10일, 12:57:01)

>>> 가져오기 다시

>>> p = re.compile(' [a-z]+')

>>>p

<80c3c28의_sre.SRE_Pattern 개체>


이제 다음을 사용해 볼 수 있습니다. RE [a-z]+는 다른 문자열과 일치합니다. +는 "1회 이상의 반복"을 의미하므로 빈 문자열은 전혀 일치하지 않습니다. 이 경우 match()는 인터프리터에 출력이 없기 때문에 None을 반환합니다. match()의 결과를 명시적으로 인쇄하여 이를 알아낼 수 있습니다.

# !python

>>> p.match("")

>>> 인쇄 p.match ("")

없음

이제 이를 사용하여 "tempo와 같은 문자열을 일치시켜 보겠습니다. ". 이 경우 match()는 MatchObject를 반환합니다. 따라서 나중에 사용하기 위해 결과를 변수에 저장할 수 있습니다.

# !python

>>>m =p.match('템포')

>> > >>이제 `MatchObject`를 쿼리하여 일치하는 문자열에 대한 관련 정보를 확인할 수 있습니다. MatchObject 인스턴스에는 다음과 같은 여러 메서드와 속성도 있습니다.
-->

#

#

# !python

p
= re.compile( )

m
= p.match( '여기에 문자열을 입력합니다' )

ifm:

인쇄 '일치 발견됨: ', m.group()

else:

인쇄 '일치 없음'

두 개의 `RegexObject` 메소드 반환 패턴과 일치하는 모든 하위 문자열. findall()은 일치하는 문자열 행 목록을 반환합니다.

#!python

>>> p = re.compile('" d+')

>>> p.findall(' 드럼 연주자 12명, 피리 부는 사람 11명, 영주 10명의 도약')

[
' 12', '11', '10']

findall()은 Python 2.2에서 결과를 반환할 때 목록을 만들어야 했습니다. , finditer() 메서드

를 사용할 수도 있습니다.

# !python

>>> 반복자 = p.finditer('12명의 드러머, 11  10 ')

>>> 반복자

<호출 가능-0x401833ac>

>>>  일치 반복자:

     
인쇄  match.span()


(0, 
2)
(
2224)
(
2931)

模块级函数

你不一定要产生一个 `RegexObject` 对象然後再调用它的方法;模块也提供了顶级函数调用如 match(), search(), sub() 等等. 적방법(返回则)要么是 None 要么就是一个 `MatchObject` 的实例。


#!python

>>>  인쇄 re.match(r'From"s+''Fromage amk')
없음


> ;>> re.match(r'From"s+''amk Thu May 14 19:12:10 1998')

<80c5978의 re.MatchObject 인스턴스>

내부적으로 이러한 함수는 단순히 RegexOject를 생성하고 그에 상응하는 메서드를 호출합니다. 또한 컴파일된 개체를 캐시에 저장하므로 동일한 RE를 사용하는 향후 호출이 더 빨라집니다.


이러한 모듈 수준 함수를 사용하시겠습니까, 아니면 `RegexObject`를 먼저 가져온 다음 해당 메서드를 호출하시겠습니까? 어떤 것을 선택하느냐는 RE와 개인 코딩 스타일의 효율성에 따라 달라집니다. RE가 코드에서 한 번만 사용되는 경우 모듈 수준 기능이 더 편리할 수 있습니다. 프로그램에 많은 정규식이 포함되어 있거나 동일한 정규식을 여러 위치에서 재사용하는 경우 모든 정의를 함께 모으고 모든 RE를 코드 블록에서 미리 컴파일하는 것이 더 유용합니다. xmllib.py 파일에서 추출된 표준 라이브러리의 예를 살펴보십시오.

#!python

ref
= re.compile( )

entityref
= re.compile( )

charref
= re.compile( )

starttagopen
= re.compile( )

나는 보통 한 번만 사용하더라도 컴파일된 객체를 사용하는 것을 선호하지만, 나만큼 이것에 대해 순수주의자인 사람은 거의 없을 것입니다.

컴파일 플래그

컴파일 플래그를 사용하면 정규식이 실행되는 방식 중 일부를 수정할 수 있습니다. re 모듈에서 플래그는 두 가지 이름을 사용할 수 있습니다. 하나는 IGNORECASE와 같은 전체 이름이고 다른 하나는 I와 같은 약어, 한 글자 형식입니다. (Perl의 모드 수정에 익숙하다면 한 글자 형태는 동일한 문자를 사용합니다. 예를 들어 re.VERBOSE의 약어는 re.X입니다.) 여러 플래그는 비트 단위 OR로 지정될 수 있습니다. 예를 들어 re.I | re.M은 I 및 M 플래그로 설정됩니다.


다음은 각 플래그 뒤에 자세한 설명이 포함된 사용 가능한 플래그 표입니다.

标志 含义
DOTALL, S 使 . 匹配包括换行在内的所有字符
IGNORECASE, I 使匹配对大小写不敏感
LOCALE, L 做本地化识别(locale-aware)匹配
MULTILINE, M 多行匹配,影响 ^ 和 $
VERBOSE, X 能够使用 REs 的 verbose 状态,使之被组织得更清晰易懂

I
IGNORECASE

문자 클래스와 문자열은 문자를 일치시킬 때 대소문자를 구분하지 않습니다. 예를 들어, [A-Z]는 소문자와 일치할 수도 있고 스팸은 "Spam", "spam" 또는 "spAM"과 일치할 수도 있습니다. 이 소문자는 현재 위치를 고려하지 않습니다.

L
LOCALE

현재 현지화 설정에 따라 "w, "W, "b 및 "B에 영향을 줍니다. .

로캘은 다양한 언어를 고려해야 하는 프로그래밍을 지원하는 데 사용되는 C 라이브러리의 기능입니다. 예를 들어, 프랑스어 텍스트로 작업하는 경우 "w+"를 사용하여 텍스트를 일치시키고 싶지만 "w는 문자 클래스 [A-Za-z]에만 일치하며 "é" 또는 "ç와는 일치하지 않습니다. ". 시스템이 적절하게 구성되고 로캘이 프랑스어로 설정된 경우 내부 C 기능은 "é"도 문자로 간주되어야 함을 프로그램에 알립니다. 정규식을 컴파일할 때 LOCALE 플래그를 사용하면 이러한 C 함수를 사용하여 "w"를 처리하는 컴파일된 개체가 생성됩니다. 이렇게 하면 속도가 느려지지만 원하는 대로 "w+를 사용하여 프랑스어 텍스트와 일치시킬 수 있습니다.

M
MULTILINE


(^ 및 $는 현재 해석되지 않으며 섹션에서 소개됩니다. 4.1 .)


문자열의 시작 부분만 일치시키려면 "^"를 사용하고, $는 문자열의 끝 부분과 개행 문자 바로 앞의 문자열 끝 부분(있는 경우)만 일치시킵니다. ). 이 플래그가 지정되면 "^"는 문자열의 시작 부분과 문자열의 각 줄의 시작 부분과 일치합니다. 마찬가지로 $ 메타문자는 문자열의 끝과 문자열의 각 줄의 끝(각 개행 바로 앞)과 일치합니다.

S
DOTALL

"." 특수 문자는 이 플래그가 없는 줄 바꿈을 포함하여 모든 문자와 정확히 일치하도록 만듭니다. " 개행 문자를 제외한 모든 문자와 일치합니다.

이해하기 쉽습니다. 이 플래그가 지정되면 공백이 문자 클래스 내에 있거나 백슬래시 뒤에 있지 않는 한 RE 문자열 내의 공백은 무시됩니다. 이를 통해 RE를 더 명확하게 구성하고 들여쓰기할 수 있습니다. 또한 엔진에서 무시되는 주석을 RE에 쓸 수 있습니다. 주석은 "#" 기호로 표시되지만 이 기호는 문자열이나 백슬래시 뒤에 올 수 없습니다.
예를 들어, re.VERBOSE를 사용하는 RE가 얼마나 읽기 쉬운지 확인해 보세요.


Actipro에서 제작한 코드 강조 표시 CodeHighlighter(프리웨어)

http://www.CodeHighlighter.com/


-->

#


#

!python
>>>
인쇄 re.search('^From ', '여기에서 영원으로')
<
80c1520의 re.MatchObject 인스턴스>
>>> ;
인쇄 re.search('^From', '기억낭송')없음

$

은 줄의 끝과 일치합니다. 이는 문자열의 끝 또는 개행 문자

뒤의 임의의 위치로 정의됩니다.

# !python

>>> 인쇄 re.search('}$''{block} ')

<80adfa8의 re.MatchObject 인스턴스>

>>> 인쇄 재검색('}$''{블록} ' )

없음

>>> 인쇄 re. search('}$''{block}"n')

<80adfa8의 re.MatchObject 인스턴스>

匹配一个 "$",使用 "$ 或将其包含在字符类中,如[$]。

"A


只匹配字符串首。当不in in MULTILINE 模式,"A 와 ^ 实际上是一样的。然而,in MULTILINE 模式里它们是不同;"A 只是匹配字符串首,而 ^ 还可以匹配에서 换行符之後字符串的任何位置。

"Z

문자열 끝에서만 일치합니다.
只匹配字符串尾。

"b

单词边界。这是个零宽界定符(너비 없는 어설션)只用以匹配单좋은词首와 词尾.单词被定义为一个字母数字序列,因此词尾就是用空白符或不字母数字符来标示的。


하면적例子只匹配 "클래스" 整个单词;而当它被包含在其他单词中时不匹配。

# !python

>>> p = re.compile(r'"bclass"b')

>>> 인쇄 p.search('수업 없음')

<80c8f28>의 re.MatchObject 인스턴스

>>> 인쇄 p.search('기밀 해제된 알고리즘')

없음

>>> 인쇄 p.search('하위 클래스 하나는')

없음

이 특정 시퀀스를 사용할 때 염두에 두어야 할 두 가지 미묘한 점이 있습니다. 첫 번째는 Python 문자열과 정규 표현식 간의 최악의 충돌입니다. Python 문자열에서 ""b"는 ​​백슬래시 문자이고 해당 ASCII 값은 8입니다. 원시 문자열을 사용하지 않으면 Python은 ""b"를 대체 문자로 변환하며 RE는 그렇지 않습니다. 원하는대로 맞출 수 있어요. 다음 예는 이전 RE와 동일해 보이지만 RE 문자열 앞에 "r"이 없습니다.

# !python

>>> p = re.compile('"bclass"b')

> ;>> 인쇄 p.search('수업 없음')

없음

>>> 인쇄 p.search('"b' + '수업' + '"b')

<80c3ee0의 re.MatchObject 인스턴스> ;

두 번째는 문자 클래스에 있으며, 이 한정자(어설션)는 효과가 없습니다. "b는 Python 문자열과의 호환성을 위한 대체 문자를 나타냅니다.

" B


"b의 반대이며 현재 위치가 단어 경계에 있지 않을 때만 일치하는 또 다른 너비가 0인 어설션입니다. >그룹

자주 RE가 일치하는지 여부보다 더 많은 정보를 얻어야 합니다. 정규식은 문자열을 분석하는 데 자주 사용됩니다. 관심 있는 부분을 일치시키고 이를 여러 그룹으로 나누는 RE를 작성합니다. 예를 들어 RFC-822 헤더는 헤더 이름으로 구분됩니다. 한 그룹은 헤더 이름과 일치하고 다른 그룹은 헤더와 일치하도록 전체 헤더와 일치하는 정규식을 작성하면 됩니다. "(" 및 ")" 메타 문자로 식별됩니다. "(" 및 ")"는 수학 표현식에서 거의 동일한 의미를 갖습니다. 예를 들어 *, +, ?와 같은 반복 한정자를 사용할 수 있습니다. (ab)*와 같이 그룹의 내용을 반복하려면 {m,n}이 0개 이상의 "ab"와 일치합니다.

Actipro에서 제작한 코드 강조 표시 CodeHighlighter(프리웨어)
http://www.CodeHighlighter.com/

--># !python

>>>p = re.compile('(a)b')

>>> m = p.match('ab')

>>> m.group()

'ab'

>>> m.group( 0)

'ab'

그룹은 1부터 시작하여 왼쪽에서 오른쪽으로 계산합니다. 그룹은 중첩될 수 있습니다. 개수의 수치는 열린 괄호의 개수를 왼쪽에서 오른쪽으로 세어 확인할 수 있습니다.

# !python

>>>p = re.compile('(a(b)c)d')

>>> m = p.match('abcd ')

>>> m.group(0)

'abcd'

>>> m.group(1)

'abc'

>>> m.group(2)

'b'

group()은 여러 그룹 번호를 동시에 입력할 수 있습니다. , 이 경우 해당 그룹에 해당하는 값을 포함하는 튜플을 반환합니다.

# !python

>>> m.group(2,1,2)

(
'b', 'abc', 'b')

groups() 메소드는
1에 포함된 그룹 번호에 .

#!python

>>> ; m.groups()
(
'abc', 'b')

패턴의 역참조를 사용하면 이전 패턴의 내용을 지정할 수 있습니다. 캡처 그룹의 경우 그룹은 문자열의 현재 위치에서도 찾아야 합니다. 예를 들어, 그룹 1의 내용을 현재 위치에서 찾을 수 있으면 "1은 성공하고, 그렇지 않으면 실패합니다. Python 문자열은 문자열에 모든 문자를 포함할 수 있도록 데이터를 추가하기 위해 백슬래시도 사용한다는 점을 기억하십시오. 역참조를 사용할 때 원시 문자열을 사용합니다. 예를 들어 다음 RE는 문자열에서 단어 쌍을 찾습니다.

Actipro CodeHighlighter(프리웨어)에서 생성된 코드 강조

http://www.CodeHighlighter.com/


-->

#

# !python

>>>m = re.match("([abc])+", "abc")

>>> m.groups()

(
'c',)

>> ;> m = re.match("(?:[abc])+", "abc")

>>> m.groups()

()

일치하는 그룹의 내용을 캡처하는 것 외에 그룹을 캡처하지 않습니다. 그룹은 정확히 동일하게 동작합니다. 그 안에 문자를 넣을 수 있고, "*"와 같은 반복 메타 문자를 사용하여 반복할 수 있으며, 다른 그룹(비캡처 그룹 및 캡처 그룹) 내에 중첩할 수 있습니다. (?:...)는 다른 그룹 번호를 모두 변경하지 않고도 새 그룹을 추가할 수 있으므로 기존 그룹을 수정하는 데 특히 유용합니다. 또한 캡처 그룹과 비캡처 그룹 간의 검색 효율성에는 차이가 없으며 어느 쪽도 다른 쪽보다 빠르지 않습니다.


둘째, 이름으로 그룹을 지정하는 것이 더 중요하고 강력합니다.


명령 그룹의 구문은 Python 관련 확장 중 하나입니다: (?P...). 이름은 분명히 그룹 이름입니다. 명명된 그룹은 그룹에 이름이 있다는 점을 제외하면 캡처링 그룹과 동일합니다. 캡처 그룹을 처리할 때 `MatchObject` 메서드는 그룹 번호를 나타내는 정수 또는 그룹 이름이 포함된 문자열을 허용합니다. 명명된 그룹은 숫자일 수도 있으므로 다음 두 가지 방법으로 그룹에 대한 정보를 얻을 수 있습니다.

#!python

> >> p = re.compile(r'(?P "b "w+"b)')

>>>m = p.search( '((((구두점이 많음))))' )

>>> m.group('')

'많음'

>>> m.group(1)

' 많음 '

이름이 지정된 그룹은 숫자를 기억할 필요 없이 기억하기 쉬운 이름을 사용할 수 있기 때문에 사용하기 편리합니다. 다음은 imaplib 모듈의 예입니다. :

#!python

InternalDate
= re.compile(r' INTERNALDATE "'

r
'(?P [ 123] [0-9])-(?P[A-Z][a-z][a-z])-'

r
'(?P[0-9][0-9][0-9][0-9])'

r
' (?P[0-9][0-9]):(?P[0-9][ 0-9 ]):(?P<초>[0-9][0-9])'

r
' (?P[-+])(?P[0-9][0-9])(?P[0-9][0-9] )'

r
'"')

분명히 m.group('zonem')을 얻는 것이 그룹 9를 얻는 것을 기억하는 것보다 훨씬 쉽습니다.


역참조 구문 때문에 (...)"1과 같은 표현은 그룹 번호를 나타냅니다. 이 경우 그룹 번호 대신 그룹 이름을 사용하면 자연스럽게 차이가 발생합니다. 또한 Python 확장: (?P=name)은 name이라는 그룹 콘텐츠를 현재 위치에서 다시 찾도록 할 수 있으며, 정규식 ("b"w+)"s+"1도 사용할 수 있습니다. (?P

#!python

>>> p = re.compile(r'(?P')

>>> p.search('봄의 파리').group()

' the'

앞 구분 기호

또 다른 너비가 0인 어설션은 앞 구분 기호입니다. 아래와 같이 정방향 양수 구분 기호 및 역방향 양수 구분 기호:

(?=...)

정방향 양수 구분 기호가 포함된 경우 다음으로 표시됩니다. ... , 현재 위치에서 성공하고 그렇지 않으면 실패하지만 일단 포함된 표현식을 시도하면 일치 엔진이 전혀 개선되지 않습니다.

(?!...)

포함된 식이 문자열에 있을 수 없는 경우 양수 구분 기호의 반대입니다.


전달이 성공할 수 있는 위치를 보여주는 데 도움이 됩니다. 파일 이름을 일치시키고 이를 기본 이름과 "."로 분할하는 간단한 패턴을 고려하십시오. 예를 들어 "news.rc"에서 "news"는 기본 이름이고 "rc"는 파일 확장자입니다.


일치 패턴은 매우 간단합니다:

.
.*[.].*$

'.'은 메타문자이므로 특별한 처리가 필요합니다. 또한 끝에 $;가 추가되어 문자열의 나머지 부분이 모두 확장자에 포함되어야 합니다. 이 정규식은


. *[.][^b].*$

위에서 "bat"를 제거하려는 첫 번째 시도에서는 확장자의 첫 번째 문자가 "b"가 아닌 다른 문자여야 합니다. 패턴이 "foo.bar"와도 일치할 수 없기 때문에 이것은 잘못된 것입니다.

. *[.]([^b]..|.[ ^a].|..[^t])$

다음 중 하나와 일치하도록 첫 번째 솔루션을 패치하려고 하면 표현식이 더욱 복잡해집니다. 확장자의 첫 번째 문자는 "b"가 아니며 두 번째 문자는 "a"가 아닙니다. 문자가 "t"가 아닙니다. 이는 "foo.bar"를 허용하지만 "autoexec.bat"를 거부합니다. 그러나 3자 확장자만 필요하고 "sendmail.cf"와 같은 2자 확장자는 허용하지 않습니다. 패치 작업을 하면서 패턴을 다시 복잡하게 만들 예정입니다.

. *[.]([^b].?.?|.[^아]?.?|..?[^t]? )$

세 번째 시도에서는 "sendmail.cf"와 같이 3자보다 짧은 확장자를 일치시킬 수 있도록 두 번째와 세 번째 문자를 모두 선택 사항으로 만들었습니다.


이제 패턴이 매우 복잡해 읽기가 어렵습니다. 더 나쁜 것은, 문제가 바뀌고 "bat"와 "exe" 이외의 확장자를 원할 경우 패턴이 훨씬 더 복잡하고 혼란스러워진다는 것입니다.


이 모든 부정 클립을

.*[.](?!bat$).* $

전진은 다음을 의미합니다. 여기서 bat 표현식이 일치하지 않으면 나머지 패턴을 시도하고 bat$가 일치하면 전체 패턴이 실패합니다. "sample.batch"와 같이 "bat"로 시작하는 확장이 허용되도록 하려면 후행 $가 필요합니다.


이제 다른 파일 확장자를 쉽게 제외할 수 있습니다. 아래 패턴은 "bat" 또는 "exe"로 끝나는 파일 이름을 제외합니다.

. *[.](?!bat$|exe$).*$

문자열 수정

지금까지는 단순히 정적 문자열을 검색했습니다. 정규 표현식은 일반적으로 아래 `RegexObject` 메서드를 통해 문자열을 수정하는 다양한 방법으로 사용됩니다.

方法/属性 作用
split() 将字符串在 RE 匹配的地方分片并生成一个列表,
sub() 找到 RE 匹配的所有子串,并将其用一个不同的字符串替换
subn() 与 sub() 相同,但返回新的字符串和替换次数

문자열 분할

`RegexObject`의 분할() 메서드는 RE가 일치하는 문자열을 분할하고 목록을 반환합니다. 이는 문자열 Split() 메서드와 유사하지만 더 많은 구분 기호를 제공합니다. Split()은 공백과 고정 문자열만 지원합니다. 예상할 수 있듯이 모듈 수준 re.split() 함수도 있습니다.

split(string [ , maxsplit = 0])

정규식을 통해 문자열을 분할합니다. RE에서 캡처링 괄호를 사용하는 경우 해당 내용도 결과 목록의 일부로 반환됩니다. maxsplit이 0이 아닌 경우 최대 maxsplit 샤드를 분할할 수 있습니다.


maxsplit 값을 설정하여 분할 횟수를 제한할 수 있습니다. maxsplit이 0이 아닌 경우 최대 maxsplit 분할이 있을 수 있으며 문자열의 나머지 부분은 목록의 마지막 부분으로 반환됩니다. 다음 예에서 구분 기호는 영숫자가 아닌 문자의 시퀀스일 수 있습니다.

# !python

>>> p = re.compile(r'"W+')

> >> p.split('split()에 대한 짧고 간단한 테스트입니다.')

[
'이것'' ''a''테스트''짧게''그리고''달콤하다 ''''분할 ''']

>>>  p.split('이것은 Split()에 대한 짧고 달콤한 테스트입니다.',3)

[
'이것' '''a''split()의 짧고 달콤한 테스트.']

여기에는 RE 中使用, 那么它们也也의 다양한 문본이 없습니다.当作列表的一返回。比较下면 적용:

# !python

>>> p = re.compile(r'"W+')

> >> p2 = re.compile(r'("W+)')

>>> p.split('이것은 테스트입니다.')

[
'이것 ''''a ''테스트''' ]

>>> p2.split(' 은 테스트입니다.')

[
'이것'' '''' '' '' ''테스트''.''']

模块级函数 re.split() 将 RE 作为第一个参数,其他一样。

# !python

>>> re.split('["W]+''말, 말, 말.' )

[
'''''''']

>>> re.split('(["W]+)''말, 말, 말. ')

[
''' ''''''''.''']

>>> re.split('["W]+ ''단어, 단어, 단어.'1)

[
''' 말, 단어.']

搜索와 替换

其他常见적용途就是找到所有模式匹配字符串并数, 和一个要替换它们。sub() 方法提供一个替换值,可以是字符串或一个函数,和一个要理被处的字符串。

sub(replacement, string[, count =  0])

반환된 문자열은 문자열에서 가장 왼쪽의 반복되지 않는 RE 일치 항목으로 대체됩니다. 패턴을 찾을 수 없으면 문자는 변경되지 않은 채 반환됩니다.


선택적 매개변수 count는 패턴 일치 후의 최대 대체 수입니다. count는 음수가 아닌 정수여야 합니다. 기본값은 모든 일치 항목을 바꾸는 0입니다.


다음은 sub() 메소드를 사용한 간단한 예입니다. 색상 이름을 "color"라는 단어로 바꿉니다.

# !python

>>>p = 재컴파일( '(파란색|흰색|빨간색)')

>>> p.sub( 'color', '파란 양말에 빨간 신발')

' 컬러 양말과 컬러 신발'

>>> p.sub( '색상', '파란 양말과 빨간 신발', 카운트=1)

'컬러 양말과 red Shoes'

subn() 메서드는 동일한 효과를 갖지만 새 문자열과 대체 실행 횟수를 포함하는 2-튜플을 반환합니다.

# !python

>>> p = 다시 컴파일( '(파란색|흰색|빨간색)')

>>> p.subn( 'color', '파란색 양말과 빨간색 신발')

(
'컬러 양말 그리고 컬러 신발', 2)

>>> p.subn( '색상', ' 색 전혀 없음')

(
'색 없음', 0)

빈 경기는 이전 경기 직후에 진행되지 않는 경우에만 교체됩니다.

# !python

>>>p = 재컴파일('x*')

>>> p.sub('-', 'abxd')

'-a-b-d- '

대체 항목이 문자열인 경우 그 안의 모든 백슬래시가 처리됩니다. ""n"은 개행 문자로 변환되고, ""r"은 캐리지 리턴 등으로 변환됩니다. ""j"와 같은 알 수 없는 이스케이프는 그대로 유지됩니다. ""6"과 같은 역참조는 RE의 해당 그룹과 일치하고 하위 문자열로 대체됩니다. 이를 통해 대체된 문자열에 원본 텍스트의 일부를 삽입할 수 있습니다.


이 예는 "{" 및 "}"로 묶인 단어 "section"을 일치시키고 "section"을 "subsection"으로 바꿉니다.

# !python

>>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)

>>> p.sub(r'하위 섹션{"1} ','섹션{첫 번째} 섹션{두 번째}')

'하위 섹션{첫 번째} 하위 섹션{두 번째}'

은 (?P ..) 구문은 명명된 그룹을 정의합니다. ""g"은 그룹 이름 "name"으로 하위 문자열과 일치하며 ""g"는 ""2와 같습니다. "이지만 ""g<2>0"과 같이 대체 문자열에서는 의미가 불분명할 수 있습니다. (""20"은 문자 "0"이 뒤에 오는 그룹 2가 아니라 그룹 20을 참조하는 것으로 해석됩니다.)

# !python

>>> p = re.compile('섹션{ (?P [^}]* ) }', re. VERBOSE)

>>> p.sub(r'하위 섹션{"1}','섹션{첫 번째}')

'하위 섹션{첫 번째}'

>>> p.sub(r'하위 섹션{"g<1>}', '섹션{첫 번째}')

'하위 섹션{첫 번째}'

>>> p.sub(r' 하위 섹션{"g}','섹션{첫 번째}')

'하위 섹션{첫 번째}'

더욱 효과적인 정책을 선택하세요.匹配所调사용.지금은 MatchObject를 사용합니다. ` 的匹配函属,并可以使用这个信息去计算预期的字符串并返回它。


바닥면에있는 편지 위치, 替换函数将十进翻译成十六进조제:

# !python

>>> def hexrepl( 일치 ):

     
"10진수에 대한 16진수 문자열 반환"

     값 
= int( match.group() )

     
반환 16진수(값)



>>> p =  re.compile(r'"d+')

> ;>> p.sub(hexrepl, '인쇄는 65490으로, 사용자 코드는 49152로 전화하세요.' )

'인쇄하려면 0xffd2를, 사용자 코드에는 0xc000을 호출하세요.'

当使用模块级的 re.sub() 函数时,模式作为第一个参数。模式也许是一个字符串或个 `RegexObject`;需要指정정정则表达式标志,你必须要么使사용 `RegexObject` 做第一个参数,或用使用模式内嵌修正器,如 sub("(?i)b+", "x", "bbbb BBBB")는 'x x'를 반환합니다.

常见问题

정확한 정보는 옳습니다.它们不按你期望的运行。本节将指些最容易犯的常见错误.

使用字符串方式

有时使用 re 模块是个错误。或单个的字符类,并且你没有使用 re 任何象 IGNORECASE 标志的功能,那么就没有必要使用 正则表达式了。字符串有一些方法是对固定字 符串进行操事 , 它们们常快很多,因为都是一个个经过优化的C 小循环,用以代替큰、更具일반적으로 사용 가능한 正则表达式引擎。


举个用一个固定字符串替换另一个的例子;如,你可以把 "행위"替换成 "단어 "。레 .sub()는 이를 위해 사용하는 함수처럼 보이지만, replacement() 메소드를 고려하십시오. 也可以에서 也可以는 进行替换, 可以把 "swordfish" 变成 "sdeedfish"로 대체됩니다. 为了避免替换单词的一分,模式将写成 "bword"b,这是为了要求 "단어" 两边有一个单词边界。这是个超流替换能력적工作)。


另一个常见任务是从一个字符串中删除单个字符或用另一个字符来替代它.你也许可以用象 re.sub('"n',' ',S) 这样来实现,但translate() 能够实现这两个任务,而且比任何正则表达式操作起来更快。

>

match() vs search()

match() 함수는 RE가 문자열의 시작 부분에서만 일치하는지 확인하는 반면, search()는 전체 문자열을 검색합니다. 이 차이점을 기억하는 것이 중요합니다. match()는 0에서 시작하는 성공적인 일치만 보고합니다. 일치가 0에서 시작하지 않으면 match()는 이를 보고하지 않습니다.

# !python

>>> 인쇄 re.match('슈퍼', '미신 ').span()

(0,
5)

>>> 인쇄 re.match('super', '초과 불가능')

없음

반면에 search()는 전체 문자열을 스캔하고 찾은 첫 번째 일치 항목을 보고합니다.

# !python

>>> 인쇄 re.search('super', '미신 ').span()

(0,
5)

>>> 인쇄 re.search('super', '매우 불가능').span()

(
2, 7)

때때로 re.match()만 사용하려는 경향이 있을 수 있습니다. if RE 앞부분에 .*를 추가합니다. 이 작업을 수행하지 말고 대신 re.search()를 사용하십시오. 정규식 컴파일러는 일치 항목을 찾을 때 처리 속도를 높이기 위해 RE에 대한 몇 가지 분석을 수행합니다. 그러한 파서 중 하나는 일치의 첫 번째 문자가 무엇인지 나타냅니다. 예를 들어 Crow 패턴은 "C"에서 시작하여 일치해야 합니다. 파서를 사용하면 엔진이 문자열을 빠르게 스캔하여 시작 문자를 찾고 "C"가 발견된 후에만 일치를 시작할 수 있습니다.

.*를 추가하면 이 최적화가 실패하게 되므로 문자열 끝까지 검색한 다음 역추적하여 RE의 나머지 부분과 일치하는 항목을 찾아야 합니다. 대신 re.search()를 사용하세요.

Greedy vs Not Greedy

a*와 같이 정규식을 반복할 경우 연산 결과는 최대한 많은 패턴을 일치시키는 것입니다. 이 사실은 HTML 마크업의 꺾쇠 괄호와 같은 대칭 구분 기호 쌍을 일치시키려고 할 때 종종 귀찮게 됩니다. 단일 HTML 태그와 일치하는 패턴은 .*

#!python

> ;>> s = '<제목> 제목'

>>> 길이

32

>>> 인쇄 re.match('<.*>', s).span()

(0,
32)

>>> 인쇄 re.match('<.*>', s).group()

<html><머리><제목>제목제목>

RE는 "<span style="font-family:新宋体"><html><code><span style="font-family:新宋体"><html></span>"의 "<"와 일치합니다. 하위 문자열의 나머지 부분. >는 문자열 끝에서 일치할 수 없지만 RE에 더 많은 것을 남겨두기 때문에 정규식은 >에 대한 일치를 찾을 때까지 문자별로 역추적해야 합니다. 최종 일치 항목은 ""의 ">"로 진행되는데 이는 원하는 결과가 아닙니다.


이 경우 해결책은 탐욕스럽지 않은 한정자 *?, +?, ?? 또는 {m,n}?를 사용하여 가능한 한 작은 텍스트를 일치시키는 것입니다. 위의 예에서 ">"는 첫 번째 "<" 직후에 시도되며, 실패하면 엔진은 한 번에 한 문자씩 증가하고 각 단계에서 ">"를 다시 시도합니다. 이 처리는 올바른 결과를 얻습니다.

#!python

pat
= re .compile(r"""

"s*                         # 선행 공백 건너뛰기

(?P

[^: ]+) # 헤더 이름

"s* :                                                                                                                                     >
# 다음 공백을 잃습니다

"s*$                                                                             줄 끝까지의 후행 공백 



"""
, re.VERBOSE)이것은 읽기가 훨씬 어렵습니다.

코드 강조 표시 작성자: Actipro CodeHighlighter(프리웨어)

http://www .CodeHighlighter.com/
#

!python
pat
=
re.compile(r""s*(?P <헤더>[^ :]+)"s*:(?P.*?)"s* $")피드백

정규식은 복잡한 주제입니다. 이 글이 이해하는 데 도움이 될까요? 해당 부분이 불분명합니까, 아니면 여기서 발견하지 못한 문제입니까? 그렇다면 작성자에게 개선을 위한 제안을 보내주세요.

정규식을 설명하는 가장 포괄적인 책은 Jeffrey Friedl이 저술하고 O'Reilly에서 출판한 "정규식 마스터하기"입니다. 아쉽게도 이 책은 Perl과 Java 스타일의 정규식에만 초점을 맞추고 Python 자료가 전혀 포함되어 있지 않아 Python 프로그래밍에 대한 참고서로는 충분하지 않습니다. (첫 번째 버전에는 자연스럽게 거의 사용되지 않는 Python의 구식 정규식 모듈이 포함되었습니다.)

위 내용은 Python 정규식 작업에 대한 자세한 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.