Escapando string regex em Python

229

Quero usar a entrada de um usuário como um padrão de expressão regular para uma pesquisa sobre algum texto. Funciona, mas como posso lidar com casos em que o usuário coloca caracteres que têm significado no regex? Por exemplo, o usuário deseja procurar o Word (s): o mecanismo de expressão regular assumirá o (s)grupo. Eu quero tratá-lo como uma corda "(s)". Posso executar replacea entrada do usuário e substituir o (com \(e o )com, \)mas o problema é que precisarei substituir todos os possíveis símbolos regex. Você conhece alguma maneira melhor?

MichaelT
fonte

Respostas:

324

Use a re.escape()função para isso:

4.2.3 reConteúdo do módulo

escape (string)

Retornar string com todos os caracteres não alfanuméricos com barra invertida; isso é útil se você deseja corresponder a uma sequência literal arbitrária que pode conter metacaracteres de expressão regular.

Um exemplo simplista, pesquise qualquer ocorrência da sequência fornecida opcionalmente seguida por 's' e retorne o objeto de correspondência.

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

Você pode usar re.escape () :

re.escape (string) Retorna string com todos os não alfanuméricos com barra invertida; isso é útil se você deseja corresponder a uma sequência literal arbitrária que pode conter metacaracteres de expressão regular.

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

Infelizmente, re.escape()não é adequado para a sequência de substituição:

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

Uma solução é colocar a substituição em um lambda:

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

porque o valor de retorno do lambda é tratado re.sub()como uma sequência literal.

Owen
fonte
3
O replargumento para re.subé uma string, não uma regex; aplicar re.escapea ele não faz sentido em primeiro lugar.
Tripleee
5
@ tripleeee Isso está incorreto, o replargumento não é uma string simples, é analisado. Por exemplo, re.sub(r'(.)', r'\1', 'X')retornará X, não \1.
Flimm
4
Aqui está a pergunta relevante para escapar do replargumento: stackoverflow.com/q/49943270/247696
Flimm
3
Alterado na versão 3.3: O caractere '_' não é mais escapado. Alterado na versão 3.7: Somente caracteres que podem ter um significado especial em uma expressão regular são escapados. (Por que demorou tanto tempo?)
Cees Timmerman