Выход из строки регулярного выражения в Python


229

Я хочу использовать ввод от пользователя в качестве шаблона регулярного выражения для поиска по некоторому тексту. Это работает, но как я могу обрабатывать случаи, когда пользователь помещает символы, которые имеют значение в регулярное выражение Например, пользователь хочет найти Word (s): движок регулярных выражений будет принимать (s)группу. Я хочу, чтобы это воспринималось как строка "(s)". Я могу работать replaceна входе пользователя и заменить (с \(и )с , \)но проблема в том , мне нужно будет сделать замену для каждого возможного символа регулярных выражений. Вы знаете какой-нибудь лучший способ?

Ответы:


324

Используйте re.escape()функцию для этого:

4.2.3 reСодержание модуля

побег (строка)

Возвращает строку со всеми не алфавитно-цифровыми обратными слэшами; это полезно, если вы хотите сопоставить произвольную литеральную строку, в которой могут быть метасимволы регулярного выражения.

Упрощенный пример: поиск в любом случае предоставленной строки, за которой необязательно следует «s», и возврат объекта соответствия.

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

53

Вы можете использовать re.escape () :

re.escape (string) Возвращает строку со всеми не алфавитно-цифровыми обратными слэшами; это полезно, если вы хотите сопоставить произвольную литеральную строку, в которой могут быть метасимволы регулярного выражения.

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

3

К сожалению, re.escape()не подходит для замены строки:

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

Решение состоит в том, чтобы поместить замену в лямбду:

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

потому что возвращаемое значение лямбда рассматривается re.sub()как литеральная строка.


3
replАргумент re.subявляется строкой, а не регулярное выражение; применять re.escapeк этому не имеет никакого смысла в первую очередь.
tripleee

5
@tripleee Это неверно, replаргумент не является простой строкой, он анализируется. Например, re.sub(r'(.)', r'\1', 'X')вернется X, а не \1.
Флимм

4
Вот соответствующий вопрос для экранирования replаргумента: stackoverflow.com/q/49943270/247696
Flimm

3
Изменено в версии 3.3: символ '_' больше не экранирован. Изменено в версии 3.7: экранируются только символы, которые могут иметь особое значение в регулярном выражении. (Почему это заняло так много времени?)
Сиз Тиммерман,

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.