Ucieczka łańcucha wyrażeń regularnych w Pythonie


229

Chcę użyć danych wejściowych od użytkownika jako wzorca wyrażeń regularnych do wyszukiwania w tekście. Działa, ale jak radzić sobie z przypadkami, w których użytkownik umieszcza w wyrażeniu regularnym znaki o znaczeniu? Na przykład użytkownik chce wyszukać (s)silnik Word : regex weźmie go (s)jako grupę. Chcę, żeby traktowało to jak strunę "(s)". Mogę uruchomić replacena danych wejściowych użytkownika i wymienić (z \(a )z \)ale jest problem będę musiał zrobić wymienić na każdym możliwym symbolem regex. Czy znasz jakiś lepszy sposób?

Odpowiedzi:


324

Użyj re.escape()do tego funkcji:

4.2.3 reZawartość modułu

escape (ciąg)

Zwraca ciąg znaków ze wszystkimi znakami odwrotnymi ukośnymi; jest to przydatne, jeśli chcesz dopasować dowolny ciąg literału, który może zawierać metaznaki wyrażenia regularnego.

Uproszczony przykład: wyszukaj dowolne wystąpienie podanego ciągu opcjonalnie po nim „s” i zwróć obiekt dopasowania.

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

53

Możesz użyć re.escape () :

re.escape (ciąg) Zwraca ciąg ze wszystkimi znakami odwrotnymi ukośnymi; jest to przydatne, jeśli chcesz dopasować dowolny ciąg literału, który może zawierać metaznaki wyrażenia regularnego.

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

3

Niestety re.escape()nie nadaje się do łańcucha zastępczego:

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

Rozwiązaniem jest umieszczenie zamiennika w lambda:

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

ponieważ zwracana wartość lambda jest traktowana re.sub()jako ciąg literalny.


3
replArgumentem re.subjest ciąg znaków, a nie regex; zastosowanie re.escapego nie ma żadnego sensu.
tripleee

5
@tripleee To niepoprawne, replargument nie jest prostym ciągiem, jest analizowany. Na przykład, re.sub(r'(.)', r'\1', 'X')powróci X, nie \1.
Flimm,

4
Oto odpowiednie pytanie pozwalające uniknąć replargumentu: stackoverflow.com/q/49943270/247696
Flimm

3
Zmieniono w wersji 3.3: Znak „_” nie jest już wybierany. Zmieniono w wersji 3.7: Wyłączane są tylko znaki, które mogą mieć specjalne znaczenie w wyrażeniu regularnym. (Dlaczego tak długo to trwało?)
Cees Timmerman,

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.