Почему мое регулярное выражение работает в X, но не в Y?

Текущие версии Fedora (и я подозреваю к настоящему времени большинство дистрибутивов) используют NetworkManager, команда nm-online должна поместить Вас онлайн, если это возможно. Проверка там не является никакими другими проблемами (слишком слабый сигнал, точка доступа фильтровала Ваш MAC, плохую установку AP, выбранный канал переполнен...).

82
16.03.2014, 06:31
1 ответ

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

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

  • требуют ли операторы +?|(){} обратного слеша;
  • какие расширения поддерживаются помимо базовых .[]*^$ и обычно +?|()

В этом ответе я перечисляю основные стандарты. За подробностями обращайтесь к документации инструментов, которые вы используете.

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

Основные регулярные выражения (BRE)

Основные регулярные выражения кодифицированы стандартом POSIX. Это синтаксис, используемый grep, sed и vi. Этот синтаксис предоставляет следующие возможности:

  • ^ и $ совпадают только в начале и конце строки.
  • . соответствует любому символу (или любому символу, кроме новой строки).
  • [...] соответствует любому символу, указанному внутри скобок (набор символов). Если первым символом после открывающей скобки является ^, то вместо него сопоставляются символы, не указанные в списке. Чтобы включить ], поставьте его сразу после открывающей [ (или после [^, если это отрицательный набор). Если -. находится между двумя символами, он обозначает диапазон; чтобы включить литерал -, поместите его туда, где он не может быть разобран как диапазон.
  • Обратная косая черта перед любым из ^$.*\[ заключает следующий символ в кавычки.
  • * совпадает с предыдущим символом или подвыражением 0, 1 или более раз.
  • \(...\) - синтаксическая группа, для использования с оператором * или обратными ссылками и заменами \DIGIT.
  • Обратные ссылки \1, \2, ... соответствуют точному тексту, найденному соответствующей группой, например, \(fo*\)\(ba*\)\1 соответствует foobaafoo, но не foobaafo. Не существует стандартного способа обозначения 10-й группы и далее (стандартное значение \10 - это первая группа, за которой следует 0).

Следующие функции также являются стандартными, но отсутствуют в некоторых ограниченных реализациях:

  • \{m,n\} соответствует предыдущему символу или подвыражению от m до n раз; n или m могут быть опущены, а \{m\} означает именно m.
  • Внутри скобок могут использоваться классы символов, например, [[:alpha:]] соответствует любой букве. Современные реализации скобочных выражений) также включают коллирующие элементы, такие как [.ll.] и классы эквивалентности, такие как [=a=].

Ниже перечислены распространенные расширения (особенно в инструментах GNU), но они встречаются не во всех реализациях. Проверьте руководство по используемому инструменту.

  • \| для чередования: foo\|bar соответствует foo или bar.
  • \? (сокращение от \{0,1\}) и \+ (сокращение от \{1,\}) совпадают с предыдущим символом или подвыражением не более 1 раза или не менее 1 раза соответственно.
  • \n соответствует новой строке, \t соответствует табуляции и т.д.
  • \w соответствует любой составляющей слова (сокращение от [_[:alnum:]], но с вариациями при локализации) и \W соответствует любому символу, который не является составляющей слова.
  • \< и \> соответствуют пустой строке только в начале или конце слова соответственно; \b соответствует любому из них, а \B соответствует там, где \b не соответствует.

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

Расширенные регулярные выражения (ERE)

Расширенные регулярные выражения кодифицированы стандартом POSIX. Их основным преимуществом перед BRE является регулярность: все стандартные операторы являются пустыми символами пунктуации, обратная косая черта перед символом пунктуации всегда заключает его в кавычки. Это синтаксис, используемый awk, grep -E или egrep, GNU sed -r и bash's =~ operator. Этот синтаксис предоставляет следующие возможности:

  • ^ и $ совпадают только в начале и конце строки.
  • . соответствует любому символу (или любому символу, кроме новой строки).
  • [...] соответствует любому символу, указанному внутри скобок (набор символов). Дополнение с начальным ^ и диапазоны работают как в BRE (см. выше). Классы символов могут быть использованы, но отсутствуют в некоторых реализациях. Современные реализации также поддерживают классы эквивалентности и элементы коллитации. Обратная косая черта внутри скобок заключает следующий символ в кавычки в некоторых, но не во всех реализациях; используйте \\\ для обозначения обратной косой черты для переносимости.
  • (...) - синтаксическая группа, для использования с заменами * или \DIGIT.
  • | для чередования: foo|bar соответствует foo или bar.
  • *, + и ? соответствует предыдущему символу или подвыражению несколько раз: 0 или более для *, 1 или более для +, 0 или 1 для ?.
  • Обратная косая черта заключает в кавычки следующий символ, если он не алфавитно-цифровой.
  • {m,n} соответствует предыдущему символу или подвыражению между m и n раз (отсутствует в некоторых реализациях); n или m могут быть опущены, а {m} означает именно m.
  • Некоторые общие расширения как в BRE: \DIGIT backreferences (отсутствует в awk, за исключением реализации busybox, где можно использовать $0 ~ "(...)\\\1"); специальные символы \n, \t и т.д. ; границы слов \b и \B, составляющие слова \b и \B, ...

PCRE (Perl-совместимые регулярные выражения)

PCRE - это расширения ERE, первоначально введенные в Perl и принятые GNU grep -P и многими современными инструментами и языками программирования, обычно через библиотеку PCRE. См. документацию по Perl для хорошего форматирования с примерами. Не все возможности последней версии Perl поддерживаются PCRE (например, выполнение кода Perl поддерживается только в Perl). См. руководство PCRE для краткого обзора поддерживаемых возможностей. Основные дополнения к ERE:

  • (?:...) - неперехватывающая группа: как (...), но не учитывается при обратных ссылках.
  • (?=FOO)BAR (lookahead) совпадает с BAR, но только если есть совпадение для FOO, начинающееся с той же позиции. Это наиболее полезно для привязки совпадения без включения в него следующего текста: foo(?=bar) соответствует foo, но только если за ним следует bar.
  • (?!FOO)BAR (отрицательное опережение) совпадает с BAR, но в той же позиции нет совпадения с FOO. Например, (?!foo)[a-z]+ соответствует любому строчному слову, которое не начинается с foo; [a-z]+(?! [0-9) соответствует любому строчному слову, за которым не следует цифра (так в foo123 соответствует fo, но не foo).
  • (?<=FOO)BAR (lookbehind) соответствует BAR, но только если ему непосредственно предшествует совпадение для FOO. FOO должен иметь известную длину (нельзя использовать операторы повторения, такие как *). Это наиболее полезно для привязки совпадения без включения в него предшествующего текста: (?<=^| )foo соответствует foo, но только если ему предшествует пробел или начало строки.
  • (? (отрицательный lookbehind) соответствует BAR, но только если ему не предшествует непосредственно совпадение с FOO. FOO должен иметь известную длину (нельзя использовать операторы повторения, такие как *). Это наиболее полезно для привязки совпадения без включения в него предшествующего текста: (? соответствует foo, но только если ему не предшествует строчная буква.

Emacs

Синтаксис Emacs является промежуточным между BRE и ERE. Помимо Emacs, это синтаксис по умолчанию для -regex в GNU find. Emacs предлагает следующие операторы:

Shell globs

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

  • ? соответствует любому одиночному символу.
  • [...] - это набор символов, как в обычных синтаксисах регулярных выражений. Некоторые оболочки не поддерживают классы символов. Некоторые оболочки требуют ! вместо ^ для отрицания набора.
  • * соответствует любой последовательности символов (часто за исключением / при поиске путей к файлам; если / исключено из *, то ** иногда включает /, но проверьте документацию инструмента).
  • Обратная косая черта цитирует следующий символ.

Ksh предлагает дополнительные возможности, которые придают его подбору шаблонов всю мощь регулярных выражений. Эти возможности также доступны в bash после выполнения shopt -s extglob. Zsh имеет другой синтаксис, но может также поддерживать синтаксис ksh после setopt ksh_glob.

112
27.01.2020, 19:30

Теги

Похожие вопросы