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

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

Это отличается от, например, Python, sed, grep, awk, Perl, переименования, Apache, find и т.д. Есть ли какой-либо набор правил, который говорит, когда я должен, а когда не должен, сбегать от специальных символов? Это зависит от типа regexp, такого как PCRE, POSIX или расширенные регулярные выражения?

Ответ 1

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

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

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

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

^-]\

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

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

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

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

[]^-]

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

.^$*[\

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

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

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

Ответ 2

Современные ароматы RegEx (PCRE)

Включает 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 может варьироваться

      Anywhere: . ^ $ * + - ? ( ) [ ] { } \ |


Legacy RegEx Flavors (BRE/ERE)

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

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

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

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

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


Примечания

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

Ответ 3

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

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

Ответ 4

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

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

Посмотрите книгу Джеффа Фридла Мастеринг по регулярным выражениям.

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

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

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

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

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

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

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

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

Не весь мир PCRE!

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

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

Ответ 8

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

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

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

Ответ 9

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

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

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

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

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

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