Escapar de la cadena de expresiones regulares en Python

229

Quiero usar la entrada de un usuario como patrón de expresiones regulares para una búsqueda en algún texto. Funciona, pero ¿cómo puedo manejar casos en los que el usuario pone caracteres que tienen significado en expresiones regulares? Por ejemplo, el usuario quiere buscar Word (s): el motor de expresiones regulares tomará el (s)como grupo. Quiero que lo trate como una cuerda "(s)". Puedo ejecutar replacela entrada del usuario y reemplazar el (con \(y el )con, \)pero el problema es que tendré que reemplazar cada símbolo de expresión regular posible. ¿Conoces alguna forma mejor?

MichaelT
fuente

Respuestas:

324

Use la re.escape()función para esto:

4.2.3 reContenido del módulo

escape (cadena)

Cadena de retorno con todos los caracteres no alfanuméricos invertidos; Esto es útil si desea hacer coincidir una cadena literal arbitraria que puede tener metacaracteres de expresión regular.

Un ejemplo simplista, busque cualquier ocurrencia de la cadena provista opcionalmente seguida de 's' y devuelva el objeto de coincidencia.

def simplistic_plural(word, text):
    word_or_plural = re.escape(word) + 's?'
    return re.match(word_or_plural, text)
ddaa
fuente
53

Puede usar re.escape () :

re.escape (string) Cadena de retorno con todas las barras no alfanuméricas invertidas; Esto es útil si desea hacer coincidir una cadena literal arbitraria que puede tener metacaracteres de expresión regular.

>>> import re
>>> re.escape('^a.*$')
'\\^a\\.\\*\\$'
gimel
fuente
3

Desafortunadamente, re.escape()no es adecuado para la cadena de reemplazo:

>>> re.sub('a', re.escape('_'), 'aa')
'\\_\\_'

Una solución es poner el reemplazo en una lambda:

>>> re.sub('a', lambda _: '_', 'aa')
'__'

porque el valor de retorno de lambda se trata re.sub()como una cadena literal.

Owen
fuente
3
El replargumento para re.subes una cadena, no una expresión regular; aplicarlo re.escapeno tiene ningún sentido en primer lugar.
tripleee
55
@tripleee Eso es incorrecto, el replargumento no es una cadena simple, se analiza. Por ejemplo, re.sub(r'(.)', r'\1', 'X')volverá X, no \1.
Flimm
44
Aquí está la pregunta relevante para escapar del replargumento: stackoverflow.com/q/49943270/247696
Flimm
3
Modificado en la versión 3.3: el carácter '_' ya no se escapa. Modificado en la versión 3.7: solo se escapan los caracteres que pueden tener un significado especial en una expresión regular.(¿Por qué tardó tanto?)
Cees Timmerman