Что такое "регулярное выражение необработанной строки" и как вы можете его использовать?
Из документации по регулярным выражениям Python, касающейся '\'
персонаж:
Решение заключается в использовании необработанной строковой нотации Python для шаблонов регулярных выражений; обратная косая черта не обрабатывается особым образом в строковом литерале с префиксом
'r'
, Такr"\n"
является двухсимвольной строкой, содержащей'\'
а также'n'
, в то время как"\n"
является односимвольной строкой, содержащей символ новой строки. Обычно шаблоны будут выражаться в коде Python с использованием этой необработанной строковой записи.
Что это за грубая нотация строк? Если вы используете формат необработанной строки, значит ли это "*"
воспринимается как буквальный символ, а не как ноль или более? Это, очевидно, не может быть правдой, иначе регулярное выражение полностью потеряет свою силу. Но тогда, если это необработанная строка, как она распознает символы новой строки, если "\n"
буквально обратный слеш и "n"
?
Я не следую
Изменить за вознаграждение:
Я пытаюсь понять, как регулярное выражение необработанной строки соответствует символам новой строки, вкладкам и наборам символов, например \w
для слов или \d
для цифр или всего такого, если шаблоны необработанных строк не распознают обратные слэши как нечто большее, чем обычные символы. Я мог бы действительно использовать несколько хороших примеров.
5 ответов
Ответ Зарконнена действительно отвечает на ваш вопрос, но не напрямую. Позвольте мне попытаться быть более прямым и посмотреть, смогу ли я получить награду у Зарконнена.
Возможно, вам будет легче это понять, если вы перестанете использовать термины "необработанное регулярное выражение строки" и "шаблоны необработанной строки". Эти термины объединяют два отдельных понятия: представления конкретной строки в исходном коде Python и то, что представляет регулярное выражение в этой строке.
На самом деле полезно думать о них как о двух разных языках программирования, каждый со своим синтаксисом. Язык Python имеет исходный код, который, помимо прочего, создает строки с определенным содержимым и вызывает систему регулярных выражений. Система регулярных выражений имеет исходный код, который находится в строковых объектах и соответствует строкам. Оба языка используют обратную косую черту в качестве escape-символа.
Во-первых, следует понимать, что строка - это последовательность символов (т. Е. Байты или кодовые точки Unicode; различие здесь не имеет большого значения). Есть много способов представить строку в исходном коде Python. Необработанная строка - просто одно из этих представлений. Если два представления приводят к одной и той же последовательности символов, они производят эквивалентное поведение.
Представьте 2-символьную строку, состоящую из символа обратной косой черты, за которым следует символ n. Если вы знаете, что значение символа для обратной косой черты равно 92, а для n равно 110, то это выражение генерирует нашу строку:
s = chr(92)+chr(110)
print len(s), s
2 \n
Традиционная нотация Python "\n"
не генерирует эту строку. Вместо этого он генерирует односимвольную строку с символом новой строки. Документы Python 2.4.1. Строковые литералы говорят: "Символ обратной косой черты (\) используется для экранирования символов, которые в противном случае имеют особое значение, таких как символ новой строки, сам обратный слэш или символ кавычки".
s = "\n"
print len(s), s
1
(Обратите внимание, что в этом примере символ новой строки не отображается, но если вы посмотрите внимательно, после "1" вы увидите пустую строку.)
Чтобы получить нашу двухсимвольную строку, мы должны использовать другой символ обратной косой черты, чтобы избежать специального значения исходного символа обратной косой черты:
s = "\\n"
print len(s), s
2 \n
Что если вы хотите представить строки, содержащие много символов обратной косой черты? Документы Python 2.4.1. Строковые литералы продолжают: "Строковые литералы могут иметь префикс с буквой" r "или"R "; такие строки называются необработанными строками и используют разные правила для интерпретации escape-последовательностей с обратной косой чертой". Вот наша двухсимвольная строка с использованием необработанного строкового представления:
s = r"\n"
print len(s), s
2 \n
Таким образом, у нас есть три разных строковых представления, все из которых дают одну и ту же строку или последовательность символов:
print chr(92)+chr(110) == "\\n" == r"\n"
True
Теперь перейдем к регулярным выражениям. Документы Python, 7.2. re
- Операции с регулярными выражениями гласят: "Регулярные выражения используют символ обратной косой черты ('\'), чтобы указать специальные формы или разрешить использование специальных символов без вызова их специального значения. Это противоречит использованию Python того же символа для той же цели в строковые литералы..."
Если вам нужен объект регулярного выражения Python, соответствующий символу новой строки, вам нужна строка из 2 символов, состоящая из символа обратной косой черты, за которым следует символ n. Следующие строки кода все устанавливают в prog объект регулярного выражения, который распознает символ новой строки:
prog = re.compile(chr(92)+chr(110))
prog = re.compile("\\n")
prog = re.compile(r"\n")
Так почему же "обычно шаблоны выражаются в коде Python с использованием этой необработанной строковой записи".? Потому что регулярные выражения часто являются статическими строками, которые удобно представлять в виде строковых литералов. А из различных доступных строковых литеральных обозначений необработанные строки являются удобным выбором, когда регулярное выражение содержит символ обратной косой черты.
Вопросы
Q: как насчет выражения re.compile(r"\s\tWord")
? A: Это легче понять, отделяя строку от компиляции регулярного выражения, и понимая их отдельно.
s = r"\s\tWord"
prog = re.compile(s)
Строка s
содержит восемь символов: обратный слеш, a s, обратный слеш, a t, а затем четыре символа Word
,
В: Что происходит с символами табуляции и пробела? A: На уровне языка Python строка s
не имеет табуляции и пробела Он начинается с четырех символов: обратная косая черта, s, обратная косая черта, t. В то же время система регулярных выражений обрабатывает эту строку как исходный код на языке регулярных выражений, где она означает "соответствовать строке, состоящей из пробела, символа табуляции и четырех символов". Word
,
Q: Как вы подходите к ним, если это рассматривается как backllash-s и backslash-t? A: Может быть, вопрос яснее, если слова "вы" и "это" сделаны более конкретными: как система регулярных выражений соответствует выражениям backlash-s и backslash-t? Как "любой символ пробела" и как "символ табуляции ".
Q: Или что если у вас есть 3-символьная строка backslash-n-newline? A: В языке Python 3-символьная строка backslash-n-newline может быть представлена в виде обычной строки "\\n\n"
или необработанная плюс обычная строка r"\n" "\n"
или другими способами. Система регулярных выражений сопоставляет 3-символьную строку backslash-n-newline, когда находит любые два последовательных символа новой строки.
NB. Все примеры и ссылки на документы относятся к Python 2.7.
Обновление: включены разъяснения из ответов @Vladislav Zorov и @m.buettner, а также из дополнительного вопроса @Aerovistae.
В большинстве этих вопросов много слов, и, возможно, трудно найти ответ на конкретный вопрос.
Если вы используете обычную строку и передаете шаблон, такой как "\t", в анализатор RegEx, Python преобразует этот литерал в буфер с байтом табуляции в нем (0x09).
Если вы используете необработанную строку и передаете шаблон, такой как r"\t", в синтаксический анализатор RegEx, Python не выполняет никакой интерпретации и создает буфер с двумя байтами в нем: '\' и 't'. (0x5c, 0x74).
Синтаксический анализатор RegEx знает, что делать с последовательностью '\t' - он сопоставляет ее с вкладкой. Он также знает, что делать с символом 0x09, который также соответствует вкладке. По большей части результаты будут неразличимы.
Таким образом, ключом к пониманию того, что происходит, является признание того, что здесь используются два парсера. Первый - это анализатор Python, и он переводит ваш строковый литерал (или необработанный строковый литерал) в последовательность байтов. Второй - это анализатор регулярных выражений Python, который преобразует последовательность байтов в скомпилированное регулярное выражение.
Проблема с использованием обычной строки для записи регулярных выражений, которые содержат \
это то, что вам в конечном итоге написать \\
для каждого \
, Так что строковые литералы "stuff\\things"
а также r"stuff\things"
произвести ту же строку. Это особенно полезно, если вы хотите написать регулярное выражение, совпадающее с обратной косой чертой.
Используя обычные строки, регулярное выражение, соответствующее строке \
было бы "\\\\"
!
Зачем? Потому что мы должны сбежать \
дважды: один раз для синтаксиса регулярного выражения и один раз для синтаксиса строки.
Вы можете использовать тройные кавычки для включения новых строк, например:
r'''stuff\
things'''
Обратите внимание, что обычно Python будет рассматривать \
-newline как продолжение строки, но это не относится к необработанным строкам. Также обратите внимание, что обратные слэши по-прежнему экранируют кавычки в необработанных строках, но остаются сами по себе. Так что необработанный строковый литерал r"\""
производит строку \"
, Это означает, что вы не можете завершить необработанный строковый литерал обратной косой чертой.
См. Раздел лексического анализа документации Python для получения дополнительной информации.
Вы, похоже, боретесь с идеей, что RegEx не является частью Python, а представляет собой другой язык программирования со своим собственным анализатором и компилятором. Необработанные строки помогают безопасно получить "исходный код" RegEx для анализатора RegEx, который затем назначит значение для последовательностей символов, таких как \d
, \w
, \n
, так далее...
Проблема существует, потому что Python и RegExps используют \
в качестве escape -символа, что, кстати, является совпадением - существуют языки с другими escape -символами (например, `` n 'для новой строки, но даже там вы должны использовать "\n" в RegExps). Преимущество состоит в том, что вам не нужно различать необработанные и не необработанные строки в этих языках, они не будут пытаться преобразовать текст и разделить его, потому что они реагируют на различные escape -последовательности.
Необработанная строка не влияет на специальные последовательности в регулярном выражении Python, такие как \w, \d. Он влияет только на escape-последовательности, такие как \n. Так что в большинстве случаев не имеет значения, пишем мы r перед или нет.
Я думаю, это ответ, который ищут большинство новичков.
Соответствующий раздел руководства по Python ("Строковые и байтовые литералы") содержит четкое объяснение необработанных строковых литералов:
Строковые и байтовые литералы могут иметь префикс в виде буквы "r" или "R"; такие строки называются необработанными строками и обрабатывают обратную косую черту как буквенные символы. В результате в строковых литералах экранирование '\U' и '\u' в необработанных строках специально не обрабатывается. Учитывая, что необработанные литералы Unicode в Python 2.x ведут себя не так, как в Python 3.x, синтаксис 'ur' не поддерживается.
Новое в версии 3.3: префикс 'rb' необработанных байтовых литералов был добавлен как синоним 'br'.
Новое в версии 3.3: Поддержка устаревшего литерала Unicode (u'value') была вновь введена, чтобы упростить обслуживание двух кодовых баз Python 2.x и 3.x. См. PEP 414 для получения дополнительной информации.
В строках с тройными кавычками допускаются (и сохраняются) неэкранированные новые строки и кавычки, за исключением того, что три неэкранированные кавычки в строке завершают строку. ("Цитата" - это символ, используемый для открытия строки, т. Е. "Или".)
Если префикс 'r' или 'R' отсутствует, escape-последовательности в строках интерпретируются в соответствии с правилами, аналогичными тем, которые используются в стандарте C. Распознаваемыми escape-последовательностями являются:
Последовательность побега Значение Примечания
\newline Обратная косая черта и новая строка игнорируются
\ Обратная косая черта ()
\ 'Одинарные кавычки (')
\ "Двойная кавычка (")
ASCII Bell (BEL)
\ b ASCII Backspace (BS)
\ f ASCII Formfeed (FF)
\ n ASCII Linefeed (LF)
Возврат каретки ASCII (CR)
\ t ASCII Горизонтальная вкладка (TAB) \v ASCII Горизонтальная вкладка (VT)
\ ooo Символ с восьмеричным значением ooo (1,3)
\ xhh Символ с шестнадцатеричным значением hh (2,3)Escape-последовательности, распознаваемые только в строковых литералах:
Escape-последовательность Значение Примечания \N{name} Имя с именем в базе данных Unicode (4) \uxxxx Символ с 16-разрядным шестнадцатеричным значением xxxx (5) \Uxxxxxxxx Символ с 32-разрядным шестнадцатеричным значением xxxxxxxx (6)
Заметки:
Как и в стандарте C, допускаются до трех восьмеричных цифр.
В отличие от стандартного C, требуется ровно две шестнадцатеричные цифры.
В байтах буквальное, шестнадцатеричное и восьмеричное экранирование обозначают байт с заданным значением. В строковом литерале эти экранирования обозначают символ Unicode с заданным значением.
Изменено в версии 3.3: Добавлена поддержка псевдонимов имен [1].
Отдельные кодовые единицы, которые образуют части суррогатной пары, могут быть закодированы с использованием этой escape-последовательности. Требуются ровно четыре шестнадцатеричные цифры.
Любой символ Юникода может быть закодирован таким образом, но символы вне Базовой многоязычной плоскости (BMP) будут закодированы с использованием суррогатной пары, если Python скомпилирован для использования 16-битных кодовых единиц (по умолчанию). Требуется ровно восемь шестнадцатеричных цифр.
В отличие от стандарта C, все нераспознанные escape-последовательности остаются в строке без изменений, т. Е. Обратный слеш остается в строке. (Это поведение полезно при отладке: если escape-последовательность набрана неверно, результирующий вывод легче распознать как поврежденный.) Также важно отметить, что escape-последовательности, распознаваемые только в строковых литералах, попадают в категорию нераспознанных escape-символов для байтов. литералы.
Даже в необработанной строке строковые кавычки можно экранировать с помощью обратной косой черты, но обратная косая черта остается в строке; например, r"\""является допустимым строковым литералом, состоящим из двух символов: обратной косой черты и двойной кавычки; r"\"не является допустимым строковым литералом (даже необработанная строка не может заканчиваться нечетным числом обратных косых черт). В частности, необработанная строка не может заканчиваться одним обратным слешем (так как обратный слеш будет экранировать следующий символ кавычки). Также обратите внимание, что одиночный обратный слеш, за которым следует символ новой строки, интерпретируется как эти два символа как часть строки, а не как продолжение строки,
\n
это escape-последовательность в Python
\w
это специальная последовательность в (Python) Regex
Они выглядят так, как будто они в одной семье, но это не так. Обозначение необработанной строки повлияет на escape-последовательности, но не на специальные последовательности регулярных выражений.
Для получения дополнительной информации о escape-последовательностях выполните поиск по запросу "\ newline" https://docs.python.org/3/reference/lexical_analysis.html
Для получения дополнительных сведений о специальных последовательностях выполните поиск по запросу "\number"https://docs.python.org/3/library/re.html.