Какие специальные символы должны быть экранированы в регулярных выражениях? - PullRequest
356 голосов
/ 30 декабря 2008

Я устал от попыток угадать, стоит ли мне избегать специальных символов, таких как '()[]{}|' и т. Д. При использовании многих реализаций регулярных выражений.

Отличается, например, Python, sed, grep, awk, Perl, переименованием, Apache, find и так далее. Существует ли какой-либо набор правил, который сообщает, когда мне следует, а когда нет, экранировать специальные символы? Зависит ли это от типа регулярного выражения, такого как PCRE, POSIX или расширенное регулярное выражение?

Ответы [ 10 ]

333 голосов
/ 30 декабря 2008

Какие символы вы должны, а какие не должны избегать, зависит от того, с каким регулярным выражением вы работаете.

Для PCRE и большинства других так называемых Perl-совместимых разновидностей, избегайте следующих внешних классов символов:

.^$*+?()[{\|

и эти внутренние классы персонажей:

^-]\

Для расширенных регулярных выражений POSIX (ERE) экранируйте эти внешние классы символов (так же, как PCRE):

.^$*+?()[{\|

Экранирование любых других символов - ошибка в POSIX ERE.

Внутри символьных классов обратная косая черта - это буквальный символ в регулярных выражениях POSIX. Вы не можете использовать это, чтобы избежать чего-либо. Вы должны использовать «умное размещение», если хотите включить метасимволы классов символов в качестве литералов. Поместите ^ где угодно, кроме как в начале,] в начале и - в начале или конце класса персонажа, чтобы они соответствовали буквально, например ::

[]^-]

В базовых регулярных выражениях POSIX (BRE) это метасимволы, которые необходимо экранировать, чтобы исключить их значение:

.^$*[\

Экранирующие скобки и фигурные скобки в BRE придают им особое значение, которое их версии без экранирования имеют в ERE. Некоторые реализации (например, GNU) также дают особое значение другим символам при экранировании, например \? и +. Экранирование символа, отличного от. ^ $ * () {}, Обычно является ошибкой для BRE.

Внутри классов персонажей BRE следуют тому же правилу, что и ERE.

Если все это заставляет вашу голову кружиться, возьмите копию RegexBuddy . На вкладке «Создать» нажмите «Вставить маркер», а затем «Литерал». RegexBuddy будет добавлять экранирование по мере необходимости.

56 голосов
/ 25 августа 2015

Современные вкусы RegEx (PCRE)

Включает C, C ++, Delphi, EditPad, Java, JavaScript, Perl, PHP (preg), PostgreSQL, PowerGREP, PowerShell, Python, REALbasic, Real Studio, Ruby, TCL, VB.Net, VBScript, wxWidgets , XML Schema, Xojo, XRegExp.
Совместимость с PCRE может варьироваться

Везде: . ^ $ * + - ? ( ) [ ] { } \ |

<Ч />

Legacy RegEx Flavors (BRE / ERE)

Включает awk, ed, egrep, emacs, GNUlib, grep, PHP (ereg), MySQL, Oracle, R, sed.
Поддержка PCRE может быть включена в более поздних версиях или с использованием расширений

ERE / AWK / задать расширенное / Emacs

Вне класса персонажа: . ^ $ * + ? ( ) [ { } \ |
Внутри класса персонажа: ^ - [ ]

BRE / Под ред / Grep / СЭД

Вне класса персонажей: . ^ $ * [ \
Внутри класса персонажа: ^ - [ ]
Для литералов не убегайте: + ? ( ) { } |
Для стандартного поведения регулярного выражения, экранируйте: \+ \? \( \) \{ \} \|

<Ч />

Примечания

  • Если вы не уверены в конкретном символе, его можно экранировать, как \xFF
  • Буквенно-цифровые символы не могут быть экранированы обратной косой чертой
  • Произвольные символы могут быть экранированы с помощью обратной косой черты в PCRE, но не BRE / ERE (они должны быть экранированы только при необходимости). Для PCRE ] - требуется только экранирование внутри класса символов, но я для простоты сохранил их в одном списке
  • В строках выражения в кавычках также должны быть экранированные символы кавычек, и часто с удвоенными обратными слешами (например, "(\")(/)(\\.)" против /(")(\/)(\.)/ в JavaScript)
  • Помимо выходов, различные реализации регулярных выражений могут поддерживать разные модификаторы, классы символов, якоря, квантификаторы и другие функции. Для получения более подробной информации, проверьте регулярные-выражения.info , или используйте regex101.com , чтобы проверить свои выражения в реальном времени
22 голосов
/ 30 декабря 2008

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

Однако сохранение такой страницы, как Страница инструментов регулярных выражений или эта Таблица регулярных выражений , может помочь вам быстро отфильтровать вещи.

5 голосов
/ 30 декабря 2008

POSIX распознает несколько вариантов регулярных выражений - базовые регулярные выражения (BRE) и расширенные регулярные выражения (ERE). И даже тогда есть причуды из-за исторических реализаций утилит, стандартизированных POSIX.

Не существует простого правила, когда использовать какую нотацию или даже какую нотацию использует данная команда.

Проверьте освоение регулярных выражений Джеффа Фридла book.

4 голосов
/ 30 декабря 2008

Иногда простое экранирование невозможно с указанными вами персонажами. Например, использование обратной косой черты для экранирования скобки не будет работать в левой части строки подстановки в sed, а именно

sed -e 's/foo\(bar/something_else/'

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

sed -e 's/foo[(]bar/something_else/'

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

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

Редактировать: После комментария ниже я подумал, что упомяну тот факт, что вы также должны учитывать разницу между автоматами с конечным состоянием и автоматами с неконечным состоянием при рассмотрении поведения вычисления регулярного выражения. .

Возможно, вы захотите взглянуть на «блестящую книгу», также называемую Effective Perl ( очищенная ссылка Amazon ), а именно на главу о регулярных выражениях, чтобы почувствовать разницу в типах оценки движка регулярных выражений.

Не во всем мире PCRE!

Так или иначе, регулярные выражения настолько неуклюжи по сравнению с СНОБОЛ ! Теперь , что было интересным курсом программирования! Вместе с тем на Simula .

Ах, радости учебы в UNSW в конце 70-х! (-:

4 голосов
/ 30 декабря 2008

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

Так что вы действительно должны знать, какой стиль вы пытаетесь процитировать.

4 голосов
/ 30 декабря 2008

Действительно, нет. существует около полумиллиона различных синтаксисов регулярных выражений; похоже, они относятся к Perl, EMACS / GNU и AT & T в целом, но я тоже всегда удивляюсь.

2 голосов
/ 05 мая 2019

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

Помните, как обрабатывается строка в памяти: if может быть простой строкой внутри кода или строкой, введенной в командную строку, но может быть либо интерактивной командной строкой, либо командной строкой, указанной в сценарии оболочки файл, или внутри переменной в памяти, упомянутой кодом, или (строковым) аргументом при дальнейшей оценке, или строкой, содержащей код, сгенерированный динамически с любой инкапсуляцией ...

Каждому этому контексту назначено несколько символов со специальным функционалом.

Когда вы хотите передать символ буквально, не используя его специальную функцию (локальную для контекста), тогда вам нужно его экранировать для следующего контекста ... который может потребовать некоторых других escape-символов, которые могут дополнительно необходимо экранировать в предыдущем контексте (ах). Кроме того, могут быть такие вещи, как кодировка символов (наиболее коварным является utf-8, потому что он выглядит как ASCII для общих символов, но может дополнительно интерпретироваться даже терминалом в зависимости от его настроек, поэтому он может вести себя по-другому, чем атрибут кодирования HTML / XML, необходимо правильно понимать процесс.

например. Регулярное выражение в командной строке, начинающееся с perl -npe, должно быть перенесено в набор системных вызовов exec , соединяющихся как канал, который обрабатывает файл, каждый из этих системных вызовов exec просто имеет список аргументов, которые были разделенные пробелами (не экранированные) и, возможно, трубами (|) и перенаправлением (> N> N> & M), скобками, интерактивным расширением * и ?, $(()) ... (все это специальные символы используется * sh, который может показаться, что мешает символу регулярного выражения в следующем контексте, но они оцениваются по порядку: перед командной строкой. Командная строка читается программой как bash / sh / csh / tcsh / zsh, по сути внутри двойной кавычки или одинарной кавычки, экранирование проще, но нет необходимости заключать в кавычки строку в командной строке, потому что в большинстве случаев пробел должен начинаться с обратной косой черты, а кавычка не требуется, оставляя доступной функциональность раскрытия для символов * и?, но этот синтаксический анализ такой же, как в цитате. Командная строка оценивается, регулярное выражение, полученное в памяти (не так, как записано в командной строке), получает ту же обработку, что и в исходном файле. Для регулярных выражений в квадратных скобках [] есть контекст набора символов, регулярное выражение perl может быть заключено в большой набор не альфа-числовых символов (например, m // или m: / better / for / path: ...).

У вас есть более подробная информация о символах в другом ответе, которые очень специфичны для конечного контекста регулярного выражения. Как я уже отмечал, вы упоминаете, что вы находите escape-выражение с попытками, возможно, потому, что другой контекст имеет другой набор символов, который запутал вашу память о попытках (часто обратный слеш - это символ, используемый в этом другом контексте для экранирования литерального символа вместо его функции. ).

2 голосов
/ 01 октября 2013

Для PHP «всегда безопаснее предшествовать не алфавитно-цифровому символу« \ », чтобы указать, что оно обозначает себя». - http://php.net/manual/en/regexp.reference.escape.php.

За исключением случаев, когда это "или".: /

Чтобы избежать переменных шаблона регулярного выражения (или частичных переменных) в PHP, используйте preg_quote ()

0 голосов
/ 19 апреля 2019

https://perldoc.perl.org/perlre.html#Quoting-metacharacters и https://perldoc.perl.org/functions/quotemeta.html

В официальном документе цитируются метасимволы:

my $regex = quotemate($string)
s/$regex/something/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...