Обратные косые черты в регулярных выражениях Python [дубликат]
этот вопрос уже есть ответ здесь:
- не удается избежать обратной косой черты с помощью regex? 5 ответов
- почему обратные косые черты появляются дважды? 2 ответы
меня смущает с обратной косой чертой в регулярных выражениях. В регулярном выражении a имеет особое значение, например
d
означает десятичную цифру. Если вы добавляете обратную косую черту перед обратной косой чертой, это особое значение теряется. В regex-howto можно прочесть:
возможно, самый важный метасимвол-это обратная косая черта,
. Как и в строковых литералах Python, обратная косая черта может сопровождаться различными символами для сигнала различных специальных последовательностей. Он также используется для побег всех метасимволов, так что вы все еще можете сопоставить их в шаблонах; например, если вам нужно соответствовать
[
или, вы можете предшествовать им с обратной косой чертой, чтобы удалить их особый смысл:
[
или.
так print(re.search('d', 'd'))
дает None
, потому что d
соответствует любой десятичной цифре, но нет в d
.
я теперь ожидал бы print(re.search('d', 'd'))
в матче d
но ответ все еще None
.
только print(re.search('\d', 'd'))
дает вывод <_sre.SRE_Match object; span=(0, 2), match='d'>
.
у кого-нибудь есть объяснение?
3 ответов
путаница связана с тем, что символ обратной косой черты \
используется как побег на двух разных уровнях. Во-первых, интерпретатор Python сам выполняет подстановки для \
до re
модуль не видит строки. Например, \n
превращается в символ новой строки, \t
преобразуется в символ табуляции и т. д. Чтобы получить фактический \
персонаж, вы можете избежать его, так что \
один \
символ. Если символ после \
не распознан escape-символ, тогда \
обрабатывается как любой другой символ и передается, но я не рекомендую в зависимости от этого. Вместо этого, всегда избежать вашего \
символы путем их удвоения, т. е. \
.
если вы хотите увидеть, как Python расширяет эскейпы строк, просто распечатайте строку. Например:
s = 'a\b\tc'
print s
если s
является частью агрегированного типа данных, например списка или кортежа, и если вы печатаете эта совокупность, Python будет заключать строку в одинарные кавычки и будет включать \
escapes (в канонической форме), поэтому имейте в виду, как печатается ваша строка. Если вы просто введете цитируемую строку в интерпретатор, она также отобразит ее, заключенную в кавычки с " \ " escapes.
как только вы узнаете, как кодируется ваша строка, вы можете подумать о том, что re
модуль сделает с ним. Например, если вы хотите избежать \
в строке вы передаете в re
модуль, вам нужно будет пройти \
to re
, что означает, что вы должны использовать \\
в вашей цитируемой строке Python. Строка Python в конечном итоге будет иметь \
и re
модуль будет рассматривать это как один литерал \
символ.
альтернативный способ включения \
символы в строках Python должны использовать необработанные строки, например r'a\b'
эквивалентно "a\b"
.
символ r перед регулярным выражением сообщает в вызове search () указывает, что регулярное выражение является необработанной строкой. Это позволяет использовать обратные косые черты в регулярном выражении как обычные символы, а не в escape-последовательности символов. Позвольте мне объяснить ...
прежде чем метод поиска модуля re обрабатывает переданные ему строки, интерпретатор Python выполняет начальный проход по строке. Если в строке присутствуют обратные косые черты, интерпретатор Python должен решить, является ли каждый из них частью escape-последовательности Python (например, \n или \t) или нет.
Примечание: На данный момент Python не волнует, является ли " \ " метасимволом регулярного выражения.
если за " \ " следует распознанный символ побега Python (t,n и т. д.), затем обратная косая черта и escape-символ заменяются фактическим Unicode или 8-битным символом. Например, "\t " будет заменен символом ASCII для tab. Иначе он передается и интерпретируется как символ"\".
учитывать следующее.
>>> s = '\t'
>>> print ("[" + s + "]")
>>> [ ] // an actual tab character after preprocessing
>>> s = '\d'
>>> print ("[" + s + "]")
>>> [\d] // '\d' after preprocessing
иногда мы хотим включить в строку последовательность символов, которая включает"\", не интерпретируемую Python как escape-последовательность. Для этого мы избегаем " \ "с"\". Теперь, когда Python видит"\", он заменяет две обратные косые черты одним символом"\".
>>> s = '\t'
>>> print ("[" + s + "]")
>>> [\t] // '\t' after preprocessing
после того, как интерпретатор Python передаст обе строки, они будут переданы метод поиска модуля re. Метод поиска анализирует строку регулярного выражения для идентификации метасимволов регулярного выражения.
теперь " \ " также является специальным метасимволом регулярного выражения и интерпретируется как один, если он не экранируется во время выполнения метода re search ().
рассмотрим следующий вызов.
>>> match = re.search('a\t','a\t') //Match is None
здесь, матч нет. Почему? Давайте посмотрим на строки после того, как интерпретатор Python делает его пройти.
String 1: 'a\t'
String 2: 'a\t'
так почему совпадение равно None? Когда search () интерпретирует строку 1, поскольку это регулярное выражение, обратная косая черта интерпретируется как мета-символ, а не обычный символ. Однако обратная косая черта в строке 2 не находится в регулярном выражении и уже обработана интерпретатором Python, поэтому она интерпретируется как обычный символ.
таким образом, метод search() ищет "escape-t" в строке "A\t", которые не являются спичка.
чтобы исправить это, мы можем сказать методу search (), чтобы не интерпретировать " \ " как мета-символ. Мы можем сделать это, сбежав от него.
рассмотрим следующий вызов.
>>> match = re.search('a\\t','a\t') // Match contains 'a\t'
опять же, давайте посмотрим на строки после того, как интерпретатор Python сделала его пройти.
String 1: 'a\t'
String 2: 'a\t'
теперь, когда метод search() обрабатывает регулярное выражение, он видит, что вторая обратная косая черта экранируется первой и не должна рассматриваться как мета-символ. Он поэтому интерпретирует строку как "A\t", которая соответствует строке 2.
альтернативный способ заставить search () рассматривать " \ " как символ-поместить r перед регулярным выражением. Это говорит интерпретатору Python не предварительно обрабатывать строку.
рассмотреть этот вопрос.
>>> match = re.search(r'a\t','a\t') // match contains 'a\t'
здесь интерпретатор Python не изменяет первую строку, но обрабатывает вторую строку. Строки, переданные в search ():
String 1: 'a\t'
String 2: 'a\t'
как и в предыдущем например, поиск интерпретирует " \ "как один символ"\", а не мета-символ, таким образом, соответствует строке 2.
собственный синтаксический анализ строки Python (частично) встает на вашем пути.
если вы хотите увидеть, что re
видит, типа
print '\d'
print '\d'
print '\\d'
в командной строке Python. Вы видите, что \d
и \d
и в результате \d
последняя заботятся интерпретатором Python строкой.
если вы хотите избежать каких-либо проблем с ними, используйте необработанные строки, как предложено документация модуля re: r'\d'
в результате \d
увиденный RE модуль.