Buscar..


Introducción

Python hace que las expresiones regulares estén disponibles a través del módulo re .

Las expresiones regulares son combinaciones de caracteres que se interpretan como reglas para hacer coincidir subcadenas. Por ejemplo, la expresión 'amount\D+\d+' coincidirá con cualquier cadena compuesta por la amount palabra más un número integral, separados por uno o más no dígitos, como: amount=100 , amount is 3 , amount is equal to: 33 , etc.

Sintaxis

  • Expresiones regulares directas

  • re.match (patrón, cadena, marca = 0) # Fuera: coincide con el patrón al principio de la cadena o Ninguno

  • re.search (patrón, cadena, marca = 0) # Fuera: coincide con el patrón dentro de la cadena o Ninguno

  • re.findall (pattern, string, flag = 0) # Out: lista de todas las coincidencias de pattern en string o []

  • re.finditer (patrón, cadena, flag = 0) # Out: igual que re.findall, pero devuelve el objeto iterador

  • re.sub (patrón, reemplazo, cadena, marca = 0) # Out: cadena con reemplazo (cadena o función) en lugar de patrón

  • Expresiones regulares precompiladas

  • precompiled_pattern = re.compile (patrón, flag = 0)

  • precompiled_pattern.match (string) # Out: coincide al principio de string o Ninguno

  • precompiled_pattern.search (string) # Out: coincide en cualquier lugar con string o None

  • precompiled_pattern.findall (string) # Out: lista de todas las subcadenas coincidentes

  • precompiled_pattern.sub (cadena / patrón / función, cadena) # Fuera: cadena reemplazada

Coincidiendo con el comienzo de una cadena

El primer argumento de re.match() es la expresión regular, el segundo es la cadena que debe coincidir:

import re

pattern = r"123"
string = "123zzb"

re.match(pattern, string)
# Out: <_sre.SRE_Match object; span=(0, 3), match='123'>

match = re.match(pattern, string)

match.group()
# Out: '123'

Puede observar que la variable de patrón es una cadena con el prefijo r , que indica que la cadena es un literal de cadena sin formato .

Una cadena prima literal tiene una sintaxis ligeramente diferente de una cadena literal, es decir, una barra invertida \ en un medio literal de cadena en bruto "sólo una barra invertida" y no hay necesidad de duplicar los juegos de escapar "secuencias de escape", tales como saltos de línea ( \n ) , tabulaciones ( \t ), espacios en blanco ( \ ), feeds de formularios ( \r ), etc. En los literales de cadena normales, cada barra invertida debe duplicarse para evitar que se tome como el inicio de una secuencia de escape.

Por lo tanto, r"\n" es una cadena de 2 caracteres: \ y n . Los patrones Regex también usan barras invertidas, por ejemplo, \d refiere a cualquier carácter de dígito. Podemos evitar tener que doble escape de nuestras cadenas ( "\\d" ) mediante el uso de cadenas sin formato ( r"\d" ).

Por ejemplo:

string = "\\t123zzb" # here the backslash is escaped, so there's no tab, just '\' and 't'
pattern = "\\t123"   # this will match \t (escaping the backslash) followed by 123
re.match(pattern, string).group()   # no match
re.match(pattern, "\t123zzb").group()  # matches '\t123'

pattern = r"\\t123"  
re.match(pattern, string).group()   # matches '\\t123'

La coincidencia se realiza desde el principio de la cadena solamente. Si quieres hacer coincidir en cualquier lugar, usa re.search en re.search lugar:

match = re.match(r"(123)", "a123zzb")

match is None
# Out: True

match = re.search(r"(123)", "a123zzb")

match.group()
# Out: '123'

buscando

pattern = r"(your base)"
sentence = "All your base are belong to us."

match = re.search(pattern, sentence)
match.group(1)
# Out: 'your base'

match = re.search(r"(belong.*)", sentence)
match.group(1)
# Out: 'belong to us.'

La búsqueda se realiza en cualquier parte de la cadena a diferencia de re.match . También puedes usar re.findall .

También puede buscar al principio de la cadena (use ^ ),

match = re.search(r"^123", "123zzb")
match.group(0)
# Out: '123'

match = re.search(r"^123", "a123zzb")
match is None
# Out: True

al final de la cadena (use $ ),

match = re.search(r"123$", "zzb123")
match.group(0)
# Out: '123'

match = re.search(r"123$", "123zzb")
match is None
# Out: True

o ambos (use ambos ^ y $ ):

match = re.search(r"^123$", "123")
match.group(0)
# Out: '123'

Agrupamiento

La agrupación se realiza entre paréntesis. El group() llamada group() devuelve una cadena formada por los subgrupos paréntesis coincidentes.

match.group() # Group without argument returns the entire match found
# Out: '123'
match.group(0) # Specifying 0 gives the same result as specifying no argument
# Out: '123'

También se pueden proporcionar argumentos a group() para obtener un subgrupo en particular.

De la documentación :

Si hay un solo argumento, el resultado es una sola cadena; Si hay varios argumentos, el resultado es una tupla con un elemento por argumento.

Al llamar a groups() por otro lado, devuelve una lista de tuplas que contienen los subgrupos.

sentence = "This is a phone number 672-123-456-9910"
pattern = r".*(phone).*?([\d-]+)"

match = re.match(pattern, sentence)

match.groups()   # The entire match as a list of tuples of the paranthesized subgroups
# Out: ('phone', '672-123-456-9910')

m.group()        # The entire match as a string
# Out: 'This is a phone number 672-123-456-9910'

m.group(0)       # The entire match as a string
# Out: 'This is a phone number 672-123-456-9910'

m.group(1)       # The first parenthesized subgroup.
# Out: 'phone'

m.group(2)       # The second parenthesized subgroup.
# Out: '672-123-456-9910'

m.group(1, 2)    # Multiple arguments give us a tuple.
# Out: ('phone', '672-123-456-9910')

Grupos nombrados

match = re.search(r'My name is (?P<name>[A-Za-z ]+)', 'My name is John Smith')
match.group('name')
# Out: 'John Smith'

match.group(1)
# Out: 'John Smith'

Crea un grupo de captura al que se puede hacer referencia por nombre y por índice.

Grupos no capturadores

Usar (?:) crea un grupo, pero el grupo no se captura. Esto significa que puede usarlo como grupo, pero no contaminará su "espacio grupal".

re.match(r'(\d+)(\+(\d+))?', '11+22').groups()
# Out: ('11', '+22', '22')

re.match(r'(\d+)(?:\+(\d+))?', '11+22').groups()
# Out: ('11', '22')

Este ejemplo coincide con 11+22 u 11 , pero no con 11+ . Esto se debe a que el signo + y el segundo término están agrupados. Por otro lado, el signo + no es capturado.

Escapar de personajes especiales

Los caracteres especiales (como los corchetes de la clase de caracteres [ y ] continuación) no se corresponden literalmente:

match = re.search(r'[b]', 'a[b]c')
match.group()
# Out: 'b'

Al escapar de los caracteres especiales, pueden emparejarse literalmente:

match = re.search(r'\[b\]', 'a[b]c')
match.group()
# Out: '[b]'

La función re.escape() se puede utilizar para hacer esto por usted:

re.escape('a[b]c')
# Out: 'a\\[b\\]c'
match = re.search(re.escape('a[b]c'), 'a[b]c')
match.group()
# Out: 'a[b]c'

La función re.escape() escapa a todos los caracteres especiales, por lo que es útil si está componiendo una expresión regular basada en la entrada del usuario:

username = 'A.C.'  # suppose this came from the user
re.findall(r'Hi {}!'.format(username), 'Hi A.C.! Hi ABCD!')
# Out: ['Hi A.C.!', 'Hi ABCD!']
re.findall(r'Hi {}!'.format(re.escape(username)), 'Hi A.C.! Hi ABCD!')
# Out: ['Hi A.C.!']

Reemplazo

Los reemplazos se pueden hacer en cadenas usando re.sub .

Reemplazo de cuerdas

re.sub(r"t[0-9][0-9]", "foo", "my name t13 is t44 what t99 ever t44")
# Out: 'my name foo is foo what foo ever foo'

Usando referencias de grupo

Los reemplazos con un pequeño número de grupos se pueden hacer de la siguiente manera:

re.sub(r"t([0-9])([0-9])", r"t\2\1", "t13 t19 t81 t25")
# Out: 't31 t91 t18 t52'

Sin embargo, si crea una ID de grupo como '10', esto no funciona : \10 se lee como 'ID número 1 seguido de 0'. Por lo tanto, debe ser más específico y usar la notación \g<i> :

re.sub(r"t([0-9])([0-9])", r"t\g<2>\g<1>", "t13 t19 t81 t25")
# Out: 't31 t91 t18 t52'

Usando una función de reemplazo

items = ["zero", "one", "two"]
re.sub(r"a\[([0-3])\]", lambda match: items[int(match.group(1))], "Items: a[0], a[1], something, a[2]")
# Out: 'Items: zero, one, something, two'

Encontrar todos los partidos no superpuestos

re.findall(r"[0-9]{2,3}", "some 1 text 12 is 945 here 4445588899")
# Out: ['12', '945', '444', '558', '889']

Tenga en cuenta que la r antes de "[0-9]{2,3}" le dice a python que interprete la cadena como está; como una cadena "sin procesar".

También puede usar re.finditer() que funciona de la misma manera que re.findall() pero devuelve un iterador con objetos SRE_Match lugar de una lista de cadenas:

results = re.finditer(r"([0-9]{2,3})", "some 1 text 12 is 945 here 4445588899")
print(results)
# Out: <callable-iterator object at 0x105245890>
for result in results:
     print(result.group(0))
''' Out:
12
945
444
558
889
'''

Patrones precompilados

import re

precompiled_pattern = re.compile(r"(\d+)")
matches = precompiled_pattern.search("The answer is 41!")
matches.group(1)
# Out: 41

matches = precompiled_pattern.search("Or was it 42?")
matches.group(1)
# Out: 42

La compilación de un patrón permite su reutilización posterior en un programa. Sin embargo, tenga en cuenta que Python almacena en caché las expresiones utilizadas recientemente ( docs , SO answer ), por lo que "los programas que usan solo unas pocas expresiones regulares a la vez no tienen que preocuparse de compilar expresiones regulares" .

import re

precompiled_pattern = re.compile(r"(.*\d+)")
matches = precompiled_pattern.match("The answer is 41!")
print(matches.group(1))
# Out: The answer is 41

matches = precompiled_pattern.match("Or was it 42?")
print(matches.group(1))
# Out: Or was it 42

Se puede utilizar con re.match ().

Comprobación de caracteres permitidos

Si desea comprobar que una cadena contiene solo un determinado conjunto de caracteres, en este caso az, AZ y 0-9, puede hacerlo así:

import re

def is_allowed(string):
    characherRegex = re.compile(r'[^a-zA-Z0-9.]')
    string = characherRegex.search(string)
    return not bool(string)
    
print (is_allowed("abyzABYZ0099")) 
# Out: 'True'

print (is_allowed("#*@#$%^")) 
# Out: 'False'

También puede adaptar la línea de expresión de [^a-zA-Z0-9.] [^a-z0-9.] , Por ejemplo, para no permitir letras en mayúsculas.

Crédito parcial: http://stackoverflow.com/a/1325265/2697955

Dividir una cadena usando expresiones regulares

También puedes usar expresiones regulares para dividir una cadena. Por ejemplo,

import re
data = re.split(r'\s+', 'James 94 Samantha 417 Scarlett 74')
print( data )
# Output: ['James', '94', 'Samantha', '417', 'Scarlett', '74']

Banderas

Para algunos casos especiales, necesitamos cambiar el comportamiento de la Expresión regular, esto se hace usando indicadores. Los indicadores se pueden establecer de dos maneras, a través de la palabra clave de flags o directamente en la expresión.

Bandera de palabras clave

Debajo de un ejemplo para re.search pero funciona para la mayoría de las funciones en el módulo re .

m = re.search("b", "ABC")  
m is None
# Out: True

m = re.search("b", "ABC", flags=re.IGNORECASE)
m.group()
# Out: 'B'

m = re.search("a.b", "A\nBC", flags=re.IGNORECASE) 
m is None
# Out: True

m = re.search("a.b", "A\nBC", flags=re.IGNORECASE|re.DOTALL) 
m.group()
# Out: 'A\nB'

Banderas comunes

Bandera Breve descripción
re.IGNORECASE , re.I Hace que el patrón ignore el caso.
re.DOTALL , re.S Hace . combina todo, incluyendo nuevas líneas
re.MULTILINE , re.M Hace ^ coincida con el comienzo de una línea y $ el final de una línea
re.DEBUG Activa la información de depuración

Para la lista completa de todas las banderas disponibles verifique los documentos

Banderas en linea

De la documentación :

(?iLmsux) (Una o más letras del conjunto 'i', 'L', 'm', 's', 'u', 'x'.)

El grupo coincide con la cadena vacía; las letras establecen los indicadores correspondientes: re.I (ignorar mayúsculas y minúsculas), re.L (dependiente del entorno local), re.M (multilínea), re.S (punto corresponde a todos), re.U (dependiente de Unicode) y re.X (verbose), para toda la expresión regular. Esto es útil si desea incluir las banderas como parte de la expresión regular, en lugar de pasar un argumento de bandera a la función re.compile ().

Tenga en cuenta que el indicador (? X) cambia la forma en que se analiza la expresión. Debe usarse primero en la cadena de expresión o después de uno o más caracteres de espacio en blanco. Si hay caracteres que no son espacios en blanco antes de la bandera, los resultados no están definidos.

Iterando sobre los partidos usando `re.finditer`

Puede usar re.finditer para iterar sobre todas las coincidencias en una cadena. Esto le proporciona (en comparación con re.findall información adicional, como información sobre la ubicación de coincidencia en la cadena (índices):

import re
text = 'You can try to find an ant in this string'
pattern = 'an?\w' # find 'an' either with or without a following word character

for match in re.finditer(pattern, text):
    # Start index of match (integer)
    sStart = match.start()

    # Final index of match (integer)
    sEnd = match.end()

    # Complete match (string)
    sGroup = match.group()

    # Print match
    print('Match "{}" found at: [{},{}]'.format(sGroup, sStart,sEnd))

Resultado:

Match "an" found at: [5,7]
Match "an" found at: [20,22]
Match "ant" found at: [23,26]

Unir una expresión solo en lugares específicos

A menudo, usted quiere hacer coincidir una expresión solo en lugares específicos (dejándolos intactos en otros, es decir). Considera la siguiente oración:

An apple a day keeps the doctor away (I eat an apple everyday).

Aquí, la "manzana" aparece dos veces, lo que se puede resolver con los llamados verbos de control de seguimiento inverso que son compatibles con el módulo de regex más nuevo. La idea es:

forget_this | or this | and this as well | (but keep this)

Con nuestro ejemplo de manzana, esto sería:

import regex as re
string = "An apple a day keeps the doctor away (I eat an apple everyday)."
rx = re.compile(r'''
    \([^()]*\) (*SKIP)(*FAIL)  # match anything in parentheses and "throw it away"
    |                          # or
    apple                      # match an apple
    ''', re.VERBOSE)
apples = rx.findall(string)
print(apples)
# only one

Esto coincide con "manzana" solo cuando se puede encontrar fuera de los paréntesis.


Así es como funciona:
  • Mientras mira de izquierda a derecha , el motor de expresiones regulares consume todo a la izquierda, (*SKIP) actúa como una "afirmación de siempre verdadera". Después, falla correctamente en (*FAIL) y retrocede.
  • Ahora llega al punto de (*SKIP) de derecha a izquierda (también conocido como retroceso) en el que está prohibido ir más hacia la izquierda. En su lugar, se le dice al motor que tire cualquier cosa a la izquierda y salte al punto donde se invocó (*SKIP) .


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow