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

254

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

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

  • 3
    Хорошие библиотеки регулярных выражений имеют функции, такие как escape() позволяющие использовать произвольные строки в качестве частей регулярных выражений.
  • 1
    Вы можете использовать онлайн-выражения Regex, такие как gskinner.com/RegExr (это бесплатно). (Введите, затем наведите курсор мыши на введенное вами регулярное выражение)
Показать ещё 5 комментариев
Теги:

8 ответов

281
Лучший ответ

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

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

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

и эти внутренние классы символов:

^-]\

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

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

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

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

[]^-]

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

.^$*

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

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

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

  • 1
    Мне кажется, вы забыли "/", который также должен быть экранирован вне класса.
  • 7
    / не является метасимволом ни в одном из упомянутых мною вариантов регулярного выражения, поэтому синтаксис регулярного выражения не требует его экранирования. Когда регулярное выражение цитируется как литерал на языке программирования, то строка или регулярных выражений правил форматирования этого языка может потребоваться / или " или ' быть экранированы, и может даже потребовать `\` , чтобы быть вдвойне убежали.
Показать ещё 14 комментариев
34

Современные ароматы 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 проверить свои выражения в режиме реального времени
  • 0
    В вашем ответе много ошибок, включая, но не ограничиваясь: ни один из ваших «современных» вариантов не требует - или ] экранирования вне классов персонажей. POSIX (BRE / ERE) не имеет escape-символа внутри классов символов. Аромат регулярных выражений в RTL Delphi фактически основан на PCRE. Python, Ruby и XML имеют свои собственные разновидности, которые ближе к PCRE, чем к POSIX.
  • 0
    @JanGoyvaerts Спасибо за исправление. Упоминаемые вами ароматы действительно ближе к PCRE. Что касается побегов, я сохранил их так для простоты; легче вспомнить, чтобы просто убежать везде, чем несколько исключений. Опытные пользователи будут знать, что случилось, если они хотят избежать нескольких обратных слешей. В любом случае, я обновил свой ответ несколькими разъяснениями, которые, надеюсь, касаются некоторых из этих вещей.
18

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

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

  • 1
    Шпаргалка Addedbytes сильно упрощена и содержит некоторые грубые ошибки. Например, он говорит, что \< и \> являются границами слов, что является истинным (AFAIK) в библиотеке регулярных выражений Boost. Но в других местах написано, что < и > являются метасимволами и должны быть экранированы (в \< и \> ), чтобы буквально соответствовать им, что не соответствует действительности.
3

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

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

Отъезд Jeff Friedl Книга "Освоение регулярных выражений" .

2

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

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

2

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

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

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

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

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

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

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

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

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

В любом случае regexp настолько неуклюжий по сравнению с SNOBOL! Теперь , который был интересным курсом программирования! Наряду с одним на Simula.

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

  • 0
    'sed' - это команда, для которой обычный '(' не является особенным, но '\ (' является особенным; напротив, PCRE меняет смысл, поэтому '(' является особенным, но '\ (' - нет. Это именно то, что ОП спрашивает о.
  • 0
    sed - это утилита * nix, которая использует один из самых примитивных наборов оценки регулярных выражений. PCRE не входит в ситуацию, которую я описываю, поскольку он включает в себя другой класс (не) конечных автоматов с тем, как он оценивает регулярные выражения. Я думаю, что мое предложение для минимального набора синтаксиса регулярных выражений все еще остается в силе.
Показать ещё 1 комментарий
1

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

0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню