Com utilitzar el mòdul d’expressions regulars de Python re (concordança, cerca, sub, etc.)

Negocis

Per dur a terme el processament d’expressions regulars a Python, utilitzem el mòdul re de la biblioteca estàndard. Us permet extreure, substituir i dividir cadenes mitjançant patrons d’expressió regular.

En aquesta secció, primer explicarem les funcions i els mètodes del mòdul re.

  • Compilació de patrons d’expressió regular:compile()
  • objecte de coincidència
  • Comproveu si el començament de la cadena coincideix, extreu:match()
  • Comproveu si hi ha coincidències no limitades al principi:search()
  • Comproveu si tota la cadena coincideix:fullmatch()
  • Obteniu una llista de totes les peces coincidents:findall()
  • Obteniu totes les parts coincidents com a iterador:finditer()
  • Substituïu la peça coincident:sub(),subn()
  • Divisió de cadenes amb patrons d’expressió regular:split()

Després d’això, explicaré els meta caràcters (caràcters especials) i les seqüències especials d’expressions regulars que es poden utilitzar al mòdul re. Bàsicament, és la sintaxi estàndard de l’expressió regular, però aneu amb compte a l’hora de configurar els indicadors (especialment re.ASCII).

  • Metacaràcters d’expressió regular, seqüències especials i advertències a Python
  • Posar la bandera
    • Limitat a caràcters ASCII:re.ASCII
    • No distingeix entre majúscules i minúscules:re.IGNORECASE
    • Relaciona l’inici i el final de cada línia:re.MULTILINE
    • Especifiqueu diverses banderes
  • Partits cobdiciosos i no cobdiciosos

Compileu el patró d’expressió regular: compile()

Hi ha dues maneres de realitzar el processament d’expressions regulars al mòdul re.

Executar amb funció

La primera és una funció.re.match(),re.sub()Funcions com aquestes estan disponibles per dur a terme l’extracció, la substitució i altres processos mitjançant patrons d’expressió regular.

Els detalls de les funcions es descriuen més endavant, però en totes elles, el primer argument és la cadena del patró d’expressió regular, seguida de la cadena a processar, etc. Per exemple, a re.sub(), que realitza la substitució, el segon argument és la cadena de substitució i el tercer argument és la cadena que s’ha de processar.

import re

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.match(r'([a-z]+)@([a-z]+)\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

result = re.sub(r'([a-z]+)@([a-z]+)\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

Tingueu en compte que [a-z] en el patró d’expressió regular d’aquest exemple significa qualsevol caràcter de la a a la z (és a dir, l’alfabet en minúscula) i + significa repetir el patró anterior (en aquest cas [a-z]) una o més vegades. [a-z]+ coincideix amb qualsevol cadena que repeteixi un o més caràcters alfabètics en minúscules.

. és un meta caràcter (un caràcter amb un significat especial) i s’ha d’escapar amb una barra invertida.

Com que les cadenes de patrons d’expressió regular sovint utilitzen moltes barres invertides, és convenient utilitzar cadenes en brut com a l’exemple.

S’executa en un mètode d’un objecte de patró d’expressió regular

La segona manera de processar expressions regulars al mòdul re és el mètode de l’objecte del patró d’expressió regular.

Amb re.compile(), podeu compilar una cadena de patró d’expressió regular per crear un objecte de patró d’expressió regular.

p = re.compile(r'([a-z]+)@([a-z]+)\.com')

print(p)
# re.compile('([a-z]+)@([a-z]+)\\.com')

print(type(p))
# <class 're.Pattern'>

re.match(),re.sub()Per exemple, el mateix procés que aquestes funcions es pot executar com a mètodes match(),sub() d’objectes d’expressió regular.

m = p.match(s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

result = p.sub('new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

Totes les funcions re.xxx() descrites a continuació també es proporcionen com a mètodes de l’objecte d’expressió regular.

Si esteu repetint un procés que utilitza el mateix patró, és més eficient generar un objecte d’expressió regular amb re.compile() i utilitzar-lo.

Al codi d’exemple següent, la funció s’utilitza sense compilar per comoditat, però si voleu utilitzar el mateix patró repetidament, es recomana compilar-lo per endavant i executar-lo com a mètode d’un objecte d’expressió regular.

objecte de coincidència

match(), search(), etc. retornen un objecte coincidència.

s = 'aaa@xxx.com'

m = re.match(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(type(m))
# <class 're.Match'>

La cadena i la posició coincidents s’obtenen mitjançant els mètodes següents de l’objecte de concordança.

  • Obteniu la ubicació del partit:start(),end(),span()
  • Obteniu la cadena coincident:group()
  • Obteniu la cadena per a cada grup:groups()
print(m.start())
# 0

print(m.end())
# 11

print(m.span())
# (0, 11)

print(m.group())
# aaa@xxx.com

Si tanqueu una part d’un patró d’expressió regular en una cadena amb parèntesis(), la part es processarà com a grup. En aquest cas, la cadena de la part que coincideix amb cada grup en groups() es pot obtenir com una tupla.

m = re.match(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(m.groups())
# ('aaa', 'xxx', 'com')

Comproveu si el començament d’una cadena coincideix, extreu: match()

match() retorna un objecte de coincidència si el començament de la cadena coincideix amb el patró.

Com s’ha esmentat anteriorment, l’objecte de concordança es pot utilitzar per extreure la subcadena coincident, o simplement per comprovar si s’ha fet una coincidència.

match() només comprovarà el principi. Si no hi ha cap cadena coincident al principi, retorna Cap.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.match(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

m = re.match(r'[a-z]+@[a-z]+\.net', s)
print(m)
# None

Comproveu si hi ha coincidències no limitades al principi, extreu: cerca ()

Igual que match(), retorna un objecte match si coincideix.

Si hi ha diverses parts coincidents, només es retornarà la primera part coincident.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

m = re.search(r'[a-z]+@[a-z]+\.net', s)
print(m)
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

m = re.search(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

Si voleu obtenir totes les parts coincidents, utilitzeu findall() o finditer() tal com es descriu a continuació.

Comproveu si tota la cadena coincideix amb: fullmatch()

Per comprovar si tota la cadena coincideix amb el patró d’expressió regular, utilitzeu fullmatch(). Això és útil, per exemple, per comprovar si una cadena és vàlida com a adreça de correu electrònic o no.

Si tota la cadena coincideix, es retorna un objecte de concordança.

s = 'aaa@xxx.com'

m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

Si hi ha parts no coincidents (només coincidències parcials o cap coincidència), es retorna Cap.

s = '!!!aaa@xxx.com!!!'

m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# None

El fullmatch() es va afegir a Python 3.4. Si voleu fer el mateix en versions anteriors, utilitzeu match() i un metacaràcter $ coincident al final. Si la cadena sencera des del principi fins al final no coincideix, retorna Cap.

s = '!!!aaa@xxx.com!!!'

m = re.match(r'[a-z]+@[a-z]+\.com$', s)
print(m)
# None

Obteniu una llista de totes les parts coincidents: findall()

findall() retorna una llista de totes les subcadenes coincidents. Tingueu en compte que els elements de la llista no són objectes de coincidència sinó cadenes.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.findall(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# ['aaa@xxx.com', 'bbb@yyy.com', 'ccc@zzz.net']

El nombre de parts coincidents es pot comprovar mitjançant la funció integrada len(), que retorna el nombre d’elements de la llista.

print(len(result))
# 3

L’agrupació amb parèntesis() en un patró d’expressió regular retorna una llista de tuples els elements de les quals són les cadenes de cada grup. Això és equivalent a groups() a l’objecte match.

result = re.findall(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(result)
# [('aaa', 'xxx', 'com'), ('bbb', 'yyy', 'com'), ('ccc', 'zzz', 'net')]

Els parèntesis del grup () es poden imbricar, de manera que si també voleu obtenir la coincidència sencera, només cal que afegiu la coincidència sencera entre parèntesis ().

result = re.findall(r'(([a-z]+)@([a-z]+)\.([a-z]+))', s)
print(result)
# [('aaa@xxx.com', 'aaa', 'xxx', 'com'), ('bbb@yyy.com', 'bbb', 'yyy', 'com'), ('ccc@zzz.net', 'ccc', 'zzz', 'net')]

Si no es troba cap coincidència, es retorna una tupla buida.

result = re.findall('[0-9]+', s)
print(result)
# []

Obteniu totes les parts coincidents com a iterador: finditer()

finditer() retorna totes les parts coincidents com a iterador. Els elements no són cadenes com findall(), sinó objectes coincidents, de manera que podeu obtenir la posició (índex) de les parts coincidents.

El propi iterador no es pot imprimir amb print() per obtenir el seu contingut. Si utilitzeu la funció integrada next() o la instrucció for, podeu obtenir el contingut un per un.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# <callable_iterator object at 0x10b0efa90>

print(type(result))
# <class 'callable_iterator'>

for m in result:
    print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

També es pot convertir en una llista amb list().

l = list(re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s))
print(l)
# [<re.Match object; span=(0, 11), match='aaa@xxx.com'>, <re.Match object; span=(13, 24), match='bbb@yyy.com'>, <re.Match object; span=(26, 37), match='ccc@zzz.net'>]

print(l[0])
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(type(l[0]))
# <class 're.Match'>

print(l[0].span())
# (0, 11)

Si voleu obtenir la posició de totes les parts coincidents, la notació de comprensió de llista és més convenient que list().

print([m.span() for m in re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)])
# [(0, 11), (13, 24), (26, 37)]

L’iterador treu els elements en ordre. Tingueu en compte que si intenteu extreure més elements després d’arribar al final, no us quedareu res.

result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)

for m in result:
    print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>

print(list(result))
# []

Substituïu les parts coincidents: sub(), subn()

Amb sub(), podeu substituir la part coincident per una altra cadena. Es retornarà la cadena substituïda.

s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'

result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net

print(type(result))
# <class 'str'>

Quan s’agrupa amb parèntesis(), la cadena coincident es pot utilitzar a la cadena substituïda.

De manera predeterminada, s’admet el següent: Tingueu en compte que per a les cadenes normals que no són cadenes en brut, s’ha d’enumerar una barra invertida abans de la barra invertida per escapar de la barra invertida.

\1El primer parèntesi
\2El segon parèntesi
\3El tercer parèntesi
result = re.sub(r'([a-z]+)@([a-z]+)\.com', r'\1@\2.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net

?P<xxx>
Si anomeneu el grup escrivint això al principi dels parèntesis del patró d’expressió regular, podeu especificar-lo fent servir el nom en comptes del número, tal com es mostra a continuació.
\g<xxx>

result = re.sub(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net

El recompte d’arguments especifica el nombre màxim de substitucions. Només es substituirà el recompte del costat esquerre.

result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# new-address, bbb@yyy.com, ccc@zzz.net

subn() retorna una tupla de la cadena substituïda (igual que el valor de retorn de sub()) i el nombre de parts substituïdes (el nombre que coincideix amb el patró).

result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# ('new-address, new-address, ccc@zzz.net', 2)

El mètode per especificar arguments és el mateix que sub(). Podeu utilitzar la part agrupada per parèntesis o especificar el nombre d’arguments.

result = re.subn(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# ('aaa@xxx.net, bbb@yyy.net, ccc@zzz.net', 2)

result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# ('new-address, bbb@yyy.com, ccc@zzz.net', 1)

Divisió de cadenes amb patrons d’expressió regular: split()

split() divideix la cadena a la part que coincideix amb el patró i la torna com a llista.

Tingueu en compte que la primera i l’última coincidència contindran cadenes buides al principi i al final de la llista resultant.

s = '111aaa222bbb333'

result = re.split('[a-z]+', s)
print(result)
# ['111', '222', '333']

result = re.split('[0-9]+', s)
print(result)
# ['', 'aaa', 'bbb', '']

L’argument maxsplit especifica el nombre màxim de divisions (peces). Només es dividirà el recompte del costat esquerre.

result = re.split('[a-z]+', s, 1)
print(result)
# ['111', '222bbb333']

Metacaràcters d’expressió regular, seqüències especials i advertències a Python

Els principals metacaràcters d’expressió regular (caràcters especials) i seqüències especials que es poden utilitzar al mòdul Python 3 re són els següents

metacaràctercontinguts
.Qualsevol caràcter que no sigui una nova línia (inclosa una nova línia amb el senyalador DOTALL)
^L’inici de la cadena (també coincideix amb el començament de cada línia amb la bandera MULTILINE)
$El final de la cadena (també coincideix amb el final de cada línia amb la bandera MULTILINE)
*Repetiu el patró anterior més de 0 vegades
+Repetiu el patró anterior almenys una vegada.
?Repetiu el patró anterior 0 o 1 vegades
{m}Repetiu el patró anterior m vegades
{m, n}L’últim patró.m~nrepetir
[]Un conjunt de personatges[]Coincideix amb qualsevol d’aquests personatges
|OA|BCoincideix amb el patró A o B
seqüència especialcontinguts
\dNúmeros decimals Unicode (limitat a números ASCII per la bandera ASCII)
\D\dVol dir el contrari d’això.
\sCaràcters d’espai en blanc Unicode (limitat a caràcters d’espai en blanc ASCII per la bandera ASCII)
\S\sVol dir el contrari d’això.
\wCaràcters de paraules Unicode i guions baixos (limitat a caràcters alfanumèrics ASCII i guions baixos per la bandera ASCII)
\W\wVol dir el contrari d’això.

No tots estan enumerats en aquesta taula. Consulteu la documentació oficial per a una llista completa.

Tingueu en compte també que alguns dels significats són diferents a Python 2.

Posar la bandera

Com es mostra a la taula anterior, alguns metacaracters i seqüències especials canvien el seu mode en funció de la bandera.

Aquí només es cobreixen les banderes principals. Consulteu la documentació oficial per a la resta.

Limitat a caràcters ASCII: re.ASCII

\wAixò també coincidirà amb kanji de doble byte, caràcters alfanumèrics, etc. per defecte per a les cadenes de Python 3. No és equivalent al següent perquè no és una expressió regular estàndard.[a-zA-Z0-9_]

m = re.match(r'\w+', '漢字ABC123')
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>

m = re.match('[a-zA-Z0-9_]+', '漢字ABC123')
print(m)
# None

Si especifiqueu re.ASCII per als indicadors d’argument de cada funció, o afegiu el següent senyalador en línia al començament de la cadena del patró d’expressió regular, només coincidirà amb caràcters ASCII (no coincidirà amb caràcters japonesos de doble byte, alfanumèrics, etc.). .).
(?a)
En aquest cas, els dos següents són equivalents.
\w#ERROR![a-zA-Z0-9_]

m = re.match(r'\w+', '漢字ABC123', flags=re.ASCII)
print(m)
# None

m = re.match(r'(?a)\w+', '漢字ABC123')
print(m)
# None

El mateix s’aplica quan es compila amb re.compile(). Utilitzeu els indicadors d’argument o els indicadors en línia.

p = re.compile(r'\w+', flags=re.ASCII)
print(p)
# re.compile('\\w+', re.ASCII)

print(p.match('漢字ABC123'))
# None

p = re.compile(r'(?a)\w+')
print(p)
# re.compile('(?a)\\w+', re.ASCII)

print(p.match('漢字ABC123'))
# None

ASCII també està disponible com a forma curta re. R. Podeu utilitzar qualsevol dels dos.

print(re.ASCII is re.A)
# True

\W, el contrari de \W, també es veu afectat per re.ASCII i senyals en línia.

m = re.match(r'\W+', '漢字ABC123')
print(m)
# None

m = re.match(r'\W+', '漢字ABC123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>

Igual que amb \w, els dos següents coincideixen amb caràcters d’un byte i de doble byte per defecte, però estan limitats a caràcters d’un sol byte si s’especifiquen senyals re.ASCII o en línia.

  • Relaciona els números\d
  • Coincideix amb un espai en blanc\s
  • Coincideix amb no números\D
  • Coincideix amb qualsevol que no sigui espai.\S
m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 3), match='123'>

m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# None

m = re.match(r'\s+', ' ')  # full-width space
print(m)
# <re.Match object; span=(0, 1), match='\u3000'>

m = re.match(r'\s+', ' ', flags=re.ASCII)
print(m)
# None

No distingeix entre majúscules i minúscules:re.IGNORECASE

Per defecte, distingeix entre majúscules i minúscules. Per fer coincidir ambdues, heu d'incloure lletres majúscules i minúscules al patró.

re.IGNORECASESi s'especifica, coincidirà sense distinció entre majúscules i minúscules. Equivalent a la bandera i en expressions regulars estàndard.

m = re.match('[a-zA-Z]+', 'abcABC')
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

m = re.match('[a-z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

m = re.match('[A-Z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>

Podeu utilitzar menys o igual a.

  • bandera en línia(?i)
  • abreviaturare.I

Relaciona l'inici i el final de cada línia:re.MULTILINE

^Els meta caràcters d'aquesta expressió regular coincideixen amb l'inici de la cadena.

Per defecte, només coincideix el principi de tota la cadena, però el següent també coincidirà amb el començament de cada línia. Equivalent a la bandera m en expressions regulars estàndard.
re.MULTILINE

s = '''aaa-xxx
bbb-yyy
ccc-zzz'''

print(s)
# aaa-xxx
# bbb-yyy
# ccc-zzz

result = re.findall('[a-z]+', s)
print(result)
# ['aaa', 'xxx', 'bbb', 'yyy', 'ccc', 'zzz']

result = re.findall('^[a-z]+', s)
print(result)
# ['aaa']

result = re.findall('^[a-z]+', s, flags=re.MULTILINE)
print(result)
# ['aaa', 'bbb', 'ccc']

$Coincideix amb el final de la cadena. Per defecte, només coincideix el final de tota la cadena.
re.MULTILINESi ho especifiqueu, també coincidirà amb el final de cada línia.

result = re.findall('[a-z]+$', s)
print(result)
# ['zzz']

result = re.findall('[a-z]+$', s, flags=re.MULTILINE)
print(result)
# ['xxx', 'yyy', 'zzz']

Podeu utilitzar menys o igual a.

  • bandera en línia(?m)
  • abreviaturare.M

Especifiqueu diverses banderes

|Si voleu habilitar diversos indicadors alhora, feu servir això. En el cas de senyals en línia, cada caràcter ha d'anar seguit d'una lletra com es mostra a continuació.
(?am)

s = '''aaa-xxx
漢漢漢-字字字
bbb-zzz'''

print(s)
# aaa-xxx
# 漢漢漢-字字字
# bbb-zzz

result = re.findall(r'^\w+', s, flags=re.M)
print(result)
# ['aaa', '漢漢漢', 'bbb']

result = re.findall(r'^\w+', s, flags=re.M | re.A)
print(result)
# ['aaa', 'bbb']

result = re.findall(r'(?am)^\w+', s)
print(result)
# ['aaa', 'bbb']

Partits cobdiciosos i no cobdiciosos

Aquest és un problema general amb les expressions regulars, no només un problema amb Python, sinó que hi escriuré perquè tendeix a posar-me en problemes.

Per defecte, la següent és una coincidència cobdiciosa, que coincideix amb la cadena més llarga possible.

  • *
  • +
  • ?
s = 'aaa@xxx.com, bbb@yyy.com'

m = re.match(r'.+com', s)
print(m)
# <re.Match object; span=(0, 24), match='aaa@xxx.com, bbb@yyy.com'>

print(m.group())
# aaa@xxx.com, bbb@yyy.com

El? després donarà lloc a una coincidència mínima i no avariciosa, que coincideixi amb la cadena més curta possible.

  • *?
  • +?
  • ??
m = re.match(r'.+?com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>

print(m.group())
# aaa@xxx.com

Tingueu en compte que la concordança cobdiciosa per defecte pot coincidir amb cadenes inesperades.

Copied title and URL