Обратные косые черты в регулярных выражениях 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 модуль.