Что такое "raw string regex" и как вы можете его использовать?

из документации python на regex, в отношении '' символ:

решение заключается в использовании необработанной Строковой нотации Python для регулярных шаблоны выражений; обратные косые черты не обрабатываются каким-либо особым образом в строковый литерал с префиксом 'r'. Так что r"n" - это двухсимвольная строка содержащий '' и 'n', а "n"-это строка символов содержит новую строку. Обычно шаблоны будут выражены в Питон код, использующий эту необработанную строковую нотацию.

что это "сырые" строковые обозначения? Если вы используете формат raw string, означает ли это "*" берется как буквальный символ, а не нулевой или более индикатор? Это, очевидно, не может быть правильным, иначе regex полностью потеряет свою силу. Но тогда, если это необработанная строка, как она распознает символы новой строки, если "n" буквально обратная косая черта и "n"?

Я не следовать.

редактировать для bounty:

Я пытаюсь понять, как необработанное регулярное выражение строки соответствует новым строкам, вкладкам и наборам символов, например w слов или d для цифр или всего прочего, если шаблоны строк raw не распознают обратные косые черты как что-то большее, чем обычные символы. Мне бы очень пригодились хорошие примеры.

5 ответов


ответ Зарконнена действительно отвечает на ваш вопрос, но не напрямую. Позвольте мне быть более откровенным и посмотреть, смогу ли я получить награду от Зарконнена.

возможно, Вам будет легче понять это, если вы перестанете использовать термины "raw string regex"и" raw string patterns". Эти термины объединяют два отдельных понятия: представления определенной строки в исходном коде Python и регулярное выражение, которое представляет эта строка.

на самом деле, это полезно думать о них как о двух разных языках программирования, каждый со своим собственным синтаксисом. Язык Python имеет исходный код, который, среди прочего, строит строки с определенным содержимым и вызывает систему регулярных выражений. Система регулярных выражений имеет исходный код, который находится в строковых объектах и соответствует строкам. В обоих языках в качестве escape-символа используется обратная косая черта.

во-первых, понимаю, что строка-это последовательность символов (т. е. байт или код Юникод пункты; различие здесь не имеет большого значения). Существует множество способов представления строки в исходном коде Python. А "сырые" строки просто одно из этих представлений. Если два представления приводят к одной и той же последовательности символов, они производят эквивалентное поведение.

представьте себе 2-символьную строку, состоящую из обратная косая черта символ, за которым следует n символ. Если вы знаете, что значение символа для обратная косая черта 92, и для n равно 110, тогда это выражение генерирует нашу строку:

s = chr(92)+chr(110)
print len(s), s

2 \n

обычная нотация строки Python "\n" не создает эту строку. Вместо этого он генерирует односимвольную строку с символом новой строки. The Python docs 2.4.1. Строковые литералы скажите: "символ обратной косой черты ( \ ) используется для escape-символов, которые в противном случае имеют особое значение, например newline, backslash сам по себе, или цитируемый персонаж."

s = "\n"
print len(s), s

1 
 

(обратите внимание, что новая строка не отображается в этом примере, но если вы внимательно посмотрите, вы увидите пустую строку после "1".)

чтобы получить нашу двухсимвольную строку, мы должны использовать другой обратная косая черта характер, чтобы избежать особого значения оригинала обратная косая черта символ:

s = "\n"
print len(s), s

2 \n

что делать, если вы хотите представить строки, которые имеют много обратная косая черта персонажи в них? Python docs 2.4.1. Строковые литералы продолжить, "строковые литералы могут дополнительно иметь префикс с буквой 'r' или 'R'; такие строки называются сырые строки и используйте различные правила для интерпретации escape-последовательностей обратной косой черты."Вот наша двухсимвольная строка, использующая представление raw string:

s = r"\n"
print len(s), s

2 \n

таким образом, у нас есть три разных строковых представления, все из которых дают одну и ту же строку или последовательность персонажи:

print chr(92)+chr(110) == "\n" == r"\n"
True

теперь перейдем к регулярным выражениям. The Python docs, 7.2. re - операции регулярного выражения говорит: "регулярные выражения используют символ обратной косой черты (' \ ' ) для обозначения специальных форм или для разрешения использования специальных символов без вызова их специального значения. Это сталкивается с использованием Python того же символа для той же цели в строковых литералах..."

если вы хотите Python регулярно объект expression, который соответствует символу новой строки, тогда вам нужна 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 обратная косая черта, an s, a обратная косая черта, a t, а затем четыре символа Word.

Q: что происходит с символами табуляции и пробела? A: на уровне языка Python string s нет tab и пробел символ. Начинается с четырех персонажи:обратная косая черта, s, обратная косая черта, t . Между тем система регулярных выражений рассматривает эту строку как исходный код на языке регулярных выражений, где это означает "сопоставьте строку, состоящую из символа пробела, символа вкладки и четырех символов Word.

Q: как вы соответствуете тем, если это рассматривается как обратная реакция-s и обратная косая черта-t? A: может вопрос яснее, если слова " вы " и " это " более конкретны: как система регулярных выражений соответствует выражениям backlash-s и backslash-t? Как "любой символ пробела" и как"tab символ'.

Q: или что, если у вас есть 3-символьная строка обратной косой черты-N-newline? A: на языке Python 3-символьная строка обратной косой черты-n-newline может быть представлена как обычная строка "\n\n", или raw plus обычная строка r"\n" "\n", или другими способами. Система регулярных выражений соответствует 3-символьной строке backslash-n-newline, когда она находит любые два последовательных newline символы.

N. B. Все примеры и ссылки на документы относятся к Python 2.7.

обновление: включены разъяснения из ответов @Vladislav Zorov и @m.buettner, и из последующего вопроса @Aerovistae.


большинство из этих вопросов имеют много слов в них, и, возможно, трудно найти ответ на ваш конкретный вопрос.

Если вы используете обычную строку и передаете шаблон типа "\t" парсеру регулярных выражений, Python переведет этот литерал в буфер с байтом вкладки в нем (0x09).

Если вы используете необработанную строку и передаете шаблон типа r "\t " синтаксическому анализатору регулярных выражений, Python не выполняет никакой интерпретации и создает буфер с двумя байтами в нем: "\"и " Т". (0x5c, 0x74).

парсер регулярных выражений знает,что делать с последовательностью '\t ' - она совпадает с вкладкой. Он также знает, что делать с символом 0x09, который также соответствует вкладке. По большей части, результаты будут неразличимы.

таким образом, ключ к пониманию того, что происходит, - это признание того, что здесь используются два парсера. Первый-синтаксический анализатор Python, и он переводит ваш строковый литерал (или необработанный строковый литерал) в последовательность байтов. Второй-анализатор регулярных выражений Python, и он преобразует последовательность байтов в скомпилированное регулярное выражение.


вы, похоже, боретесь с идеей, что регулярное выражение не является частью Python, а вместо этого другим языком программирования с собственным синтаксическим анализатором и компилятором. Необработанные строки помогут вам безопасно получить "исходный код" регулярного выражения в синтаксическом анализаторе регулярных выражений, который затем присвоит значение последовательностям символов, таким как \d, \w, \n, etc...

проблема существует, потому что Python и RegExps используют \ как escape-символ, который, кстати, является совпадением-есть языки с другими escape-символами (например, "`n" для новой строки, но даже там вы должны использовать "\n" в регулярных выражениях). Преимущество заключается в том, что вам не нужно различать необработанные и необработанные строки на этих языках, они не будут пытаться преобразовать текст и разделать его, потому что они реагируют на разные escape-последовательности.


проблема с использованием обычной строки для записи регулярных выражений, содержащих \ это то, что вы в конечном итоге должны написать \ для каждого \. Итак, строковые литералы "stuff\things" и r"stuff\things" создайте ту же строку. Это особенно полезно, если вы хотите написать регулярное выражение, которое соответствует обратным косым чертам.

используя обычные строки, регулярное выражение, которое соответствует строке \ будет "\\"!

почему? Потому что мы должны бежать \ в два раза: один раз для синтаксиса регулярного выражения и один раз для синтаксиса строки.

вы можете использовать тройные кавычки для включения новых строк, например:

r'''stuff\
things'''

обратите внимание, что обычно python будет лечить \ - newline как продолжение строки, но это не относится к необработанным строкам. Также обратите внимание, что обратные косые черты по-прежнему экранируют кавычки в необработанных строках, но остаются сами по себе. Итак, необработанный строковый литерал r"\"" производит строку \". Это означает, что вы не можете закончить необработанную строку буквальный с обратной косой чертой.

посмотреть раздел лексического анализа документации Python для получения дополнительной информации.


соответствующий раздел руководства Python ("строковые и байтовые литералы") имеет четкое объяснение необработанных строковых литералов:

Как строку и Байт литералы могут быть с префиксом буква " r " или "R"; такие строки называются необработанными строками и обрабатываются символы как символы. В результате, в строковых литералах, '\U 'и' \u ' escapes в необработанных строках не обрабатываются специально. С учетом что Python 2.необработанные литералы unicode x ведут себя иначе, чем Python 3.X синтаксис' ur ' не поддерживается.

новое в версии 3.3: префикс' rb ' литералов необработанных байтов был добавлено как синоним 'br'.

новое в версии 3.3: поддержка устаревшего литерала unicode (u'value) был вновь введен для упрощения обслуживания dual Python 2.x и 3.х сборок. См. PEP 414 для получения дополнительной информации.

в тройных кавычках, неэкранированные символы новой строки и цитаты (и сохраняются), за исключением трех неэкранированные кавычки подряд завершите строку. ("Цитата" - это символ, используемый для открытия строка, то есть либо', либо ".)

Если префикс' r 'или' R ' не присутствует, escape-последовательности в строках интерпретируются в соответствии с правилами, аналогичными используемым стандартом С. признан escape-последовательности:

Escape-Последовательность Значение Примечания

\Newline обратная косая черта и newline игнорируется
\ Обратная косая черта ()
\' Одинарная кавычка (')
\" Двойная кавычка (")
\ ASCII Bell (BEL)
\ B ASCII Backspace (BS)
\ F ASCII Formfeed (FF)
\ N ASCII Linefeed (LF)
\R ASCII возврат каретки (CR)
\ T ASCII горизонтальная вкладка (TAB) \ V ASCII вертикальная вкладка (VT)
\ ooo характер с восьмеричным значением ooo (1,3)
\xhh символ с шестнадцатеричным значением ДХ (2,3)

Escape-последовательности распознаются только в строковых литералах:

Escape-Последовательности Значение Примечания \N{name} символ с именем name в База данных Юникода (4) \uxxxx символ с 16-разрядным шестнадцатеричным значением xxxx (5) \Символ Uxxxxxxxx с 32-разрядным шестнадцатеричным значением хххххххх (6)

Примечания:

  1. Как и в стандартном C, принимаются до трех восьмеричных цифр.

  2. в отличие от стандартного C, требуется ровно две шестнадцатеричные цифры.

  3. в байтовом литерале шестнадцатеричный и восьмеричный escapes обозначают байт с заданным значением. В строковом литерале эти escapes обозначают a Символ Юникода с заданным значением.

  4. изменено в версии 3.3: добавлена поддержка псевдонимов имен [1].

  5. отдельные кодовые единицы, которые образуют части суррогатной пары, могут быть закодированы с помощью этой escape-последовательности. Ровно четыре шестнадцатеричные цифры требуемый.

  6. любой символ Unicode может быть закодирован таким образом, но персонажи вне базовой многоязычной плоскости (BMP) будет кодироваться с помощью суррогатная пара, если Python компилируется для использования 16-битных кодовых единиц ( неисполнение.) Требуется ровно восемь шестнадцатеричных цифр.

В отличие от стандартного C, все непризнанные escape-последовательности остаются в строка не изменяется, т. е. обратная косая черта остается в строке. (Этот поведение полезно при отладке: если escape-последовательность-это неправильно, полученный результат легче распознать как сломанный.) Он также важно отметить, что escape-последовательности распознаются только в строке литералы попадают в категорию нераспознанных escapes для байтов константы.

даже в необработанной строке строковые кавычки могут быть экранированы с обратной косой чертой, но обратная косая черта в строке; например, р"\"", является действительным строковый литерал, состоящий из двух символов: обратной косой черты и двойного quote; r " \ " не является допустимым строковым литералом (даже необработанная строка не может конец в нечетном числе обратная косая черта.) В частности, необработанная строка не может заканчиваться одной обратной косой чертой (так как обратная косая черта следующие кавычки). Отметим также, что один слеш по новой строке интерпретируется как эти два символа как часть строка, а не как продолжение строки.