Регулярное выражение - Regular expression

Результаты совпадения шаблона
(?<=\.) {2,}(?=[A-Z])
Соответствуют как минимум два пробела, но только если они встречаются непосредственно после точки (.) И перед заглавной буквой.
Стивен Коул Клини , который представил концепцию
Черный список в Википедии, в котором используются регулярные выражения для определения плохих заголовков.

Регулярное выражение (укорочен регулярное выражение или регулярное выражение , также упоминается как рациональное выражение ) представляет собой последовательность символов , которая задает поиск шаблона . Обычно такие шаблоны используются алгоритмами поиска по строкам для операций «найти» или «найти и заменить» над строками или для проверки ввода. Это метод, разработанный в теоретической информатике и теории формального языка .

Идея регулярных выражений зародилась в 1950-х годах, когда американский математик Стивен Коул Клини формализовал описание регулярного языка . Они стали широко использоваться с утилитами обработки текста Unix . Различные синтаксисы для написания регулярных выражений существуют с 1980-х годов, один из которых является стандартом POSIX, а другой, широко используемым, является синтаксисом Perl .

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

История

Регулярные выражения возникли в 1951 году, когда математик Стивен Коул Клини описал регулярные языки, используя свою математическую нотацию, названную регулярными событиями . Они возникли в теоретической информатике , в подполях теории автоматов (модели вычислений) и описания и классификации формальных языков . Другие ранние реализации сопоставления с образцом включают язык SNOBOL , в котором не использовались регулярные выражения, а вместо этого использовались собственные конструкции сопоставления с образцом.

Регулярные выражения стали широко использоваться с 1968 года в двух случаях: сопоставление с образцом в текстовом редакторе и лексический анализ в компиляторе. Одним из первых появлений регулярных выражений в форме программы было то, что Кен Томпсон встроил нотацию Клини в редактор QED как средство сопоставления шаблонов в текстовых файлах . Для ускорения работы Томпсон реализовал сопоставление регулярных выражений с помощью своевременной компиляции (JIT) к коду IBM 7094 в Совместимой системе разделения времени , важном раннем примере JIT-компиляции. Позже он добавил эту возможность в редактор ed Unix , что в конечном итоге привело к тому, что популярный инструмент поиска grep стал использовать регулярные выражения («grep» - это слово, производное от команды для поиска по регулярным выражениям в редакторе ed: что означает «Глобальный поиск»). для регулярных выражений и совпадающих строк печати "). Примерно в то же время, когда Томпсон разработал QED, группа исследователей, включая Дугласа Т. Росс, реализовала инструмент, основанный на регулярных выражениях, который используется для лексического анализа при проектировании компиляторов . g/re/p

Многие варианты этих исходных форм регулярных выражений использовались в программах Unix в Bell Labs в 1970-х годах, включая vi , lex , sed , AWK и expr , а также в других программах, таких как Emacs . Впоследствии регулярные выражения были приняты в широком спектре программ, причем эти ранние формы были стандартизированы в стандарте POSIX.2 в 1992 году.

В 1980-х годах более сложные регулярные выражения возникли в Perl , который первоначально был получен из библиотеки регулярных выражений, написанной Генри Спенсером (1986), который позже написал реализацию расширенных регулярных выражений для Tcl . Библиотека Tcl - это гибридная реализация NFA / DFA с улучшенными характеристиками производительности. Программные проекты, в которых реализована реализация регулярных выражений Spencer Tcl, включают PostgreSQL . Позже Perl расширил исходную библиотеку Спенсера, добавив много новых функций. Часть усилий при разработке Raku (ранее называвшейся Perl 6) заключается в улучшении интеграции регулярных выражений Perl, а также в увеличении их объема и возможностей, позволяющих определять грамматики синтаксического анализа выражений . В результате появился мини-язык под названием правила Raku , который используется для определения грамматики Raku, а также предоставляет программистам инструмент на этом языке. Эти правила поддерживают существующие функции регулярных выражений Perl 5.x, но также позволяют определять рекурсивный анализатор спуска в стиле BNF с помощью подправил.

Использование регулярных выражений в стандартах структурированной информации для моделирования документов и баз данных началось в 1960-х и расширилось в 1980-х, когда были объединены отраслевые стандарты, такие как ISO SGML (предшественник ANSI "GCA 101-1983"). Ядро стандартов языка спецификации структур состоит из регулярных выражений. Его использование очевидно в синтаксисе группы элементов DTD .

Начиная с 1997 года Филип Хейзел разработал PCRE (Perl-совместимые регулярные выражения), который пытается точно имитировать функциональность регулярных выражений Perl и используется многими современными инструментами, включая PHP и HTTP-сервер Apache .

Сегодня регулярные выражения широко поддерживаются в языках программирования, программах обработки текста (особенно лексерах ), расширенных текстовых редакторах и некоторых других программах. Поддержка Regex является частью стандартной библиотеки многих языков программирования, включая Java и Python , и встроена в синтаксис других языков, включая Perl и ECMAScript . Реализации функций регулярных выражений часто называют механизмом регулярных выражений , и для повторного использования доступен ряд библиотек. В конце 2010-х несколько компаний начали предлагать аппаратные средства, FPGA , реализации GPU для PCRE- совместимых механизмов регулярных выражений, которые работают быстрее по сравнению с реализациями CPU .

Узоры

Фраза регулярные выражения или регулярные выражения часто используется для обозначения определенного стандартного текстового синтаксиса для представления шаблонов для сопоставления текста, в отличие от математической нотации, описанной ниже. Каждый символ в регулярном выражении (то есть каждый символ в строке, описывающей его шаблон) является либо метасимволом , имеющим особое значение, либо обычным символом, имеющим буквальное значение. Например, в регулярном выражении b."b" - это буквальный символ, который соответствует только "b", а "." - это метасимвол, который соответствует каждому символу, кроме новой строки. Следовательно, это регулярное выражение соответствует, например, «b%», «bx» или «b5». Вместе метасимволы и буквальные символы могут использоваться для идентификации текста данного шаблона или обработки ряда его экземпляров. Соответствие шаблонов может варьироваться от точного равенства до очень общего подобия, что определяется метасимволами. Например, .это очень общий шаблон [a-z](соответствует всем строчным буквам от «a» до «z») является менее общим и bточным (соответствует только «b»). Синтаксис метасимвола разработан специально для краткого и гибкого представления предписанных целей для управления автоматизацией обработки текста различных входных данных в форме, удобной для ввода с использованием стандартной клавиатуры ASCII .

Очень простой случай регулярного выражения в этом синтаксисе - найти слово, написанное двумя разными способами в текстовом редакторе , регулярное выражение seriali[sz]eсоответствует как «сериализовать», так и «сериализовать». Подстановочные знаки также достигают этого, но они более ограничены в том, что они могут создавать, поскольку у них меньше метасимволов и простая языковая база.

Обычный контекст подстановочных знаков - это подстановка похожих имен в списке файлов, тогда как регулярные выражения обычно используются в приложениях, которые в целом сопоставляют текстовые строки с шаблоном. Например, регулярное выражение соответствует лишнему пробелу в начале или конце строки. Расширенное регулярное выражение, которое соответствует любой цифре, - это . ^[ \t]+|[ \t]+$[+-]?(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?

Воплощение в Клини звезды
( S * означает «ноль или более с »)

Процессор регулярного выражения преобразует регулярное выражение в приведенном выше синтаксисе во внутреннее представление , которое может быть выполнено , и согласованным против строки , представляющего текст досматриваемого. Один из возможных подходов состоят в алгоритме построения Томпсона построить недетерминированный конечный автомат (НКА), который затем делается детерминированным, и полученный детерминированный конечный автомат (DFA) запускается в целевой текстовой строке для распознавания подстрок, соответствующих регулярному выражению. На рисунке показана схема NFA, полученная из регулярного выражения , где s, в свою очередь, обозначает более простое регулярное выражение, которое уже было рекурсивно переведено в NFA N ( s ). N(s*)s*

Базовые концепты

Регулярное выражение, часто называемое шаблоном , определяет набор строк, необходимых для определенной цели. Простой способ указать конечный набор строк - перечислить его элементы или члены. Однако часто есть более сжатые способы: например, набор, содержащий три строки «Гендель», «Гендель» и «Гендель», может быть определен шаблоном H(ä|ae?)ndel; мы говорим, что этот шаблон соответствует каждой из трех строк. В большинстве формализмов , если существует хотя бы одно регулярное выражение, которое соответствует определенному набору, тогда существует бесконечное количество других регулярных выражений, которые также соответствуют ему - спецификация не уникальна. Большинство формализмов предоставляют следующие операции для построения регулярных выражений.

Логическое "или"
Вертикальная полоса отделяет альтернативу. Например, может соответствовать «серый» или «серый».gray|grey
Группировка
Круглые скобки используются для определения объема и приоритета операторов (среди прочего). Например, gray|greyи являются эквивалентными шаблонами, которые оба описывают набор «серый» или «серый».gr(a|e)y
Количественная оценка
Квантификатором после маркера (например, символ) или группы указывает , как часто , что предшествующий элемент разрешено иметь место. Наиболее распространенными количественными показателями являются вопросительный знак ? , звездочка * (образованная от звезды Клини ) и знак плюса + ( Клини плюс ).
? Знак вопроса указывает на ноль или одно вхождение предыдущего элемента. Например, colou?rсоответствует как «цвет», так и «цвет».
* Звездочка указывает ноль или более вхождений предыдущего элемента. Например, ab*cсоответствует «ac», «abc», «abbc», «abbbc» и так далее.
+ Знак плюс указывает одно или несколько вхождений предыдущего элемента. Например, ab+cсоответствует «abc», «abbc», «abbbc» и т. Д., Но не «ac».
{n} Предыдущий элемент соответствует ровно n раз.
{min,} Предыдущий элемент встречается минимум минимум раз.
{,max} Предыдущий элемент соответствует максимуму раз.
{min,max} Предыдущий элемент соответствует минимум минимум раз, но не больше максимум раз.
Подстановочный знак

Подстановочный знак .соответствует любому символу. Например, a.bсоответствует любой строке, содержащей «a», затем любому другому символу, а затем «b», a.*bсоответствует любой строке, содержащей «a», а затем символ «b» в какой-то более поздний момент.

Эти конструкции можно комбинировать для образования произвольно сложных выражений, подобно тому, как можно создавать арифметические выражения из чисел и операций +, -, × и ÷. Например, H(ae?|ä)ndelи оба являются допустимыми шаблонами, которые соответствуют тем же строкам, что и в предыдущем примере ,. H(a|ae|ä)ndelH(ä|ae?)ndel

Точный синтаксис регулярных выражений зависит от инструментов и контекста; более подробно см. в § Синтаксис .

Теория формального языка

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

Формальное определение

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

  • ( пустое множество ) ∅, обозначающее множество ∅.
  • ( пустая строка ) ε обозначает набор, содержащий только «пустую» строку, в которой вообще нет символов.
  • ( буквальный символ ) aв Σ, обозначающий множество, содержащее только символ a .

Учитывая регулярные выражения R и S, для создания регулярных выражений над ними определены следующие операции:

  • ( конкатенация ) (RS)обозначает набор строк, который может быть получен путем конкатенации строки, принятой R, и строки, принятой S (в этом порядке). Например, пусть R обозначает {"ab", "c"}, а S обозначает {"d", "ef"}. Затем (RS)обозначает {"abd", "abef", "cd", "cef"}.
  • ( чередование ) (R|S)обозначает объединение множеств множеств, описываемых R и S. Например, если R описывает {"ab", "c"}, а S описывает {"ab", "d", "ef"}, выражение (R|S)описывает { «ab», «c», «d», «ef»}.
  • ( Звездочка Клини ) (R*)обозначает наименьшее надмножество множества, описываемого R, которое содержит ε и закрывается при конкатенации строк. Это набор всех строк, который может быть создан путем конкатенации любого конечного числа (включая ноль) строк из набора, описанного R. Например, если R обозначает {"0", "1"}, (R*)обозначает набор всех конечные двоичные строки (включая пустую строку). Если R обозначает {"ab", "c"}, (R*)обозначает {ε, "ab", "c", "abab", "abc", "cab", "cc", "ababab", "abcab",. ..}.

Чтобы избежать скобок, предполагается, что звезда Клини имеет наивысший приоритет, затем объединение, а затем чередование. Если нет двусмысленности, скобки можно опустить. Например, (ab)cможно записать как abc, а a|(b(c*))можно записать как a|bc*. Во многих учебниках вместо вертикальной черты для чередования используются символы ∪, + или ∨.

Примеры:

  • a|b* обозначает {ε, "a", "b", "bb", "bbb", ...}
  • (a|b)* обозначает набор всех строк без символов, кроме «a» и «b», включая пустую строку: {ε, «a», «b», «aa», «ab», «ba», «bb» , "ааа", ...}
  • ab*(c|ε) обозначает набор строк, начинающийся с «a», затем ноль или более «b» s и, наконец, необязательно «c»: {«a», «ac», «ab», «abc», «abb», «abbc» ", ...}
  • (0|(1(01*0)*1))* обозначает набор двоичных чисел, кратных 3: {ε, «0», «00», «11», «000», «011», «110», «0000», «0011», «0110» , «1001», «1100», «1111», «00000», ...}

Выразительная мощь и компактность

Формальное определение регулярных выражений является минимальным намеренно и избегает определения ?и +- они могут быть выражены следующим образом: a+= aa*и a?= (a|ε). Иногда дополнение оператор добавлен, чтобы дать обобщенную регулярное выражение ; здесь R с соответствует всем строкам над Е * , которые не соответствуют R . В принципе, оператор дополнения избыточен, потому что он не дает более выразительной силы. Однако он может сделать регулярное выражение намного более кратким - исключение единственного оператора дополнения может привести к двойному экспоненциальному увеличению его длины.

Регулярные выражения в этом смысле могут выражать регулярные языки, в точности класс языков, принимаемых детерминированными конечными автоматами . Однако есть существенная разница в компактности. Некоторые классы регулярных языков могут быть описаны только детерминированными конечными автоматами, размер которых растет экспоненциально по мере увеличения размера кратчайших эквивалентных регулярных выражений. Стандартным примером здесь являются языки L k, состоящие из всех строк в алфавите { a , b }, у которых k- я с последней буквы равна  a . С одной стороны, регулярное выражение, описывающее L 4, имеет вид .

Обобщение этого шаблона на L k дает выражение:

С другой стороны, известно, что каждый детерминированный конечный автомат, принимающий язык L k, должен иметь не менее 2 k состояний. К счастью, существует простое отображение регулярных выражений в более общие недетерминированные конечные автоматы (NFA), которое не приводит к такому увеличению размера; по этой причине NFA часто используются как альтернативные представления обычных языков. NFAS представляют собой простое изменение типа-3 грамматик в иерархии Хомского .

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

По заданному регулярному выражению алгоритм построения Томпсона вычисляет эквивалентный недетерминированный конечный автомат. Преобразование в обратном направлении достигается алгоритмом Клини .

Наконец, стоит отметить, что многие реальные движки «регулярных выражений» реализуют функции, которые не могут быть описаны регулярными выражениями в смысле теории формального языка; скорее они реализуют регулярные выражения . Подробнее об этом см. Ниже .

Определение эквивалентности регулярных выражений

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

Можно написать алгоритм, который для двух заданных регулярных выражений определяет, равны ли описанные языки; алгоритм сводит каждое выражение к минимальному детерминированному конечному автомату и определяет, являются ли они изоморфными (эквивалентными).

Алгебраические законы для регулярных выражений могут быть получены с использованием метода Гишера, который лучше всего объясняется на примере: чтобы проверить, обозначают ли ( X + Y ) * и ( X * Y * ) * один и тот же регулярный язык для всех регулярных выражений X , Y , необходимо и достаточно проверить, обозначают ли конкретные регулярные выражения ( a + b ) * и ( a * b * ) * один и тот же язык в алфавите Σ = { a , b }. В более общем смысле, уравнение E = F между членами регулярного выражения с переменными выполняется тогда и только тогда, когда выполняется его экземпляр с разными переменными, замененными разными символьными константами.

Избыточность можно устранить, используя звездочку Клини и объединение множеств, чтобы найти интересное подмножество регулярных выражений, которые по-прежнему полностью выразительны, но, возможно, их использование может быть ограничено. Это на удивление сложная проблема. Какими бы простыми ни были регулярные выражения, не существует метода их систематического преобразования в некоторую нормальную форму. Отсутствие аксиомы в прошлом привело к проблеме высоты звезды . В 1991 году Декстер Козен аксиоматизировал регулярные выражения как алгебру Клини , используя аксиомы уравнения и предложения Хорна . Уже в 1964 году Редько доказал, что никакой конечный набор чисто эквациональных аксиом не может характеризовать алгебру регулярных языков.

Синтаксис

Шаблон регулярного выражения соответствует целевой строке . Узор состоит из последовательности атомов . Атом - это единственная точка в шаблоне регулярного выражения, которую он пытается сопоставить с целевой строкой. Самый простой атом - это литерал, но группировка частей шаблона для соответствия атому потребует использования в ( )качестве метасимволов. Метасимволы помогают сформировать: атомы ; кванторы, сообщающие, сколько атомов (и является ли это жадным квантификатором ); логический символ OR, который предлагает набор альтернатив, и логический символ NOT, который отрицает существование атома; и обратные ссылки для ссылки на предыдущие атомы завершающей структуры атомов. Сопоставление происходит не тогда, когда совпадают все атомы строки, а, скорее, когда совпадают все атомы шаблона в регулярном выражении. Идея состоит в том, чтобы сделать небольшой набор символов обозначением большого количества возможных строк, а не составлять большой список всех буквальных возможностей.

В зависимости от процессора регулярных выражений существует около четырнадцати метасимволов, символов, которые могут иметь или не иметь буквальное значение символа, в зависимости от контекста или от того, являются ли они «экранированными», то есть им предшествует escape-последовательность , в данном случае обратная косая черта \. В современных регулярных выражениях и расширенных регулярных выражениях POSIX метасимволы используются чаще, чем их буквальное значение, поэтому, чтобы избежать "обратной косой черты" или синдрома наклонной зубочистки, имеет смысл переводить метасимвол в буквальный режим; но для начала имеет смысл иметь четыре заключенных в скобки метасимвола ( )и { }быть в первую очередь буквальным и «избегать» этого обычного значения, чтобы стать метасимволами. Общие стандарты реализуют оба. Обычные метасимволы - это {}[]()^$.|*+?и \. Обычные символы, которые при экранировании становятся метасимволами, - это dswDSWи N.

Разделители

При вводе регулярного выражения на языке программирования они могут быть представлены как обычные строковые литералы, поэтому обычно заключаются в кавычки; это распространено, например, в C, Java и Python, где регулярное выражение reвводится как "re". Однако они часто пишутся с косой чертой в качестве разделителей , как в /re/регулярном выражении re. Это происходит из ed , где /находится команда редактора для поиска, и выражение /re/может использоваться для указания диапазона строк (совпадающих с шаблоном), которые можно комбинировать с другими командами с любой стороны, наиболее известной из которых g/re/pявляется grep ("global regex print "), который включен в большинство операционных систем на базе Unix , таких как дистрибутивы Linux . Аналогичное соглашение используется в sed , где поиск и замена задаются с помощью, s/re/replacement/а шаблоны могут быть объединены запятой, чтобы указать диапазон строк, как в /re1/,/re2/. Эта нотация особенно хорошо известна благодаря ее использованию в Perl , где она составляет часть синтаксиса, отличную от обычных строковых литералов. В некоторых случаях, таких как sed и Perl, можно использовать альтернативные разделители, чтобы избежать столкновения с содержимым и избежать необходимости экранировать вхождения символа-разделителя в содержимом. Например, в sed команда s,/,X,заменит a /на a X, используя запятые в качестве разделителей.

Стандарты

Стандарт IEEE POSIX имеет три набора соответствия: BRE (базовые регулярные выражения), ERE (расширенные регулярные выражения) и SRE (простые регулярные выражения). SRE устарел в пользу BRE, поскольку оба обеспечивают обратную совместимость . Подраздел, описывающий классы персонажей, применим как к BRE, так и к ERE.

BRE и ERE работают вместе. ERE добавляет ?, +и |, и устраняет необходимость экранировать метасимволы ( )и { }, которые требуются в BRE. Более того, пока соблюдается стандартный синтаксис POSIX для регулярных выражений, может быть и часто бывает дополнительный синтаксис для обслуживания конкретных (но совместимых с POSIX) приложений. Хотя в POSIX.2 некоторые особенности реализации остаются неопределенными, BRE и ERE предоставляют «стандарт», который с тех пор был принят в качестве синтаксиса по умолчанию для многих инструментов, где обычно поддерживается выбор режимов BRE или ERE. Например, GNU grep имеет следующие параметры: « grep -E» для ERE и « grep -G» для BRE (по умолчанию) и « grep -P» для регулярных выражений Perl .

Регулярные выражения Perl стали стандартом де-факто, имея богатый и мощный набор атомарных выражений. Perl не имеет «базовых» или «расширенных» уровней. Как и в POSIX EREs, ( )и { }рассматриваются как метасимволы , если не спаслись; другие метасимволы, как известно, являются буквальными или символическими, исходя только из контекста. Дополнительные функции включают ленивое сопоставление , обратные ссылки , именованные группы захвата и рекурсивные шаблоны.

POSIX базовый и расширенный

В стандарте POSIX базовый регулярный синтаксис ( BRE ) требует, чтобы метасимволы ( ) и { }были обозначены \(\)и \{\}, тогда как расширенный регулярный синтаксис ( ERE ) этого не делает.

Метасимвол Описание
^ Соответствует начальной позиции в строке. В линейных инструментах он соответствует начальной позиции любой строки.
. Соответствует любому одиночному символу (многие приложения исключают новые строки , и какие именно символы считаются новыми строками, зависит от вкуса, кодировки символов и платформы, но можно с уверенностью предположить, что символ перевода строки включен). В выражениях скобок POSIX символ точки соответствует буквальной точке. Например, a.cсоответствует «abc» и т. Д., Но [a.c]соответствует только «a», «.» Или «c».
[ ] Выражение в скобках. Соответствует одиночному символу, заключенному в квадратные скобки. Например, [abc]соответствует «a», «b» или «c». [a-z]указывает диапазон, который соответствует любой строчной букве от «a» до «z». Эти формы могут быть смешаны: [abcx-z]соответствует «a», «b», «c», «x», «y» или «z» [a-cx-z].

Символ -считается буквальным, если он является последним или первым (после ^символа, если он присутствует) в квадратных скобках: [abc-], [-abc]. Обратите внимание, что экранирование обратной косой черты не допускается. ]Символ может быть включен в выражение в квадратных скобках , если он является первым (после ^) символа: []abc].

[^ ] Соответствует одиночному символу, не заключенному в квадратные скобки. Например, [^abc]соответствует любому символу, кроме «a», «b» или «c». [^a-z]соответствует любому одиночному символу, который не является строчной буквой от «a» до «z». Таким же образом можно смешивать буквальные символы и диапазоны.
$ Соответствует конечной позиции строки или позиции непосредственно перед новой строкой, заканчивающейся строкой. В линейных инструментах он соответствует конечной позиции любой строки.
( ) Определяет отмеченное подвыражение. Строку, указанную в скобках, можно будет вызвать позже (см. Следующую запись ). Отмеченное подвыражение также называется блоком или группой захвата. Для режима BRE требуется . \n\( \)
\n Соответствует тому, чему соответствует n- е отмеченное подвыражение, где n - это цифра от 1 до 9. Эта конструкция неопределенно определена в стандарте POSIX.2. Некоторые инструменты позволяют ссылаться на более чем девять групп захвата. Также известна как обратная ссылка.
* Соответствует предыдущему элементу ноль или более раз. Например, ab*cсоответствует «ac», «abc», «abbbc» и т. Д. Соответствует « [xyz]*», «x», «y», «z», «zx», «zyx», «xyzzy» и так далее. (ab)*соответствует "", "ab", "abab", "ababab" и так далее.
{m,n} Соответствует предыдущему элементу не менее m и не более n раз. Например, a{3,5}соответствует только «ааа», «аааа» и «ааааа». Этого нет в нескольких старых экземплярах регулярных выражений. Для режима BRE требуется\{m,n\} .

Примеры:

  • .at соответствует любой трехсимвольной строке, оканчивающейся на "at", включая "шляпу", "кот" и "летучую мышь".
  • [hc]at соответствует «шляпа» и «кот».
  • [^b]atсоответствует всем строкам, за .atисключением "летучей мыши".
  • [^hc]atсоответствует всем строкам, .atкроме "hat" и "cat".
  • ^[hc]at соответствует «шляпе» и «кошке», но только в начале строки или строки.
  • [hc]at$ соответствует «шляпе» и «кошке», но только в конце строки или строки.
  • \[.\] соответствует любому одиночному символу, окруженному «[» и «]», поскольку скобки экранированы, например: «[a]» и «[b]».
  • s.* соответствует s, за которым следует ноль или более символов, например: «s», «saw» и «seed».

POSIX расширенный

Значение метасимволов, экранированных обратной косой чертой, меняется на обратное для некоторых символов в синтаксисе расширенного регулярного выражения POSIX ( ERE ). В этом синтаксисе обратная косая черта приводит к тому, что метасимвол обрабатывается как буквальный символ. Так, например, \( \)сейчас ( )и \{ \}есть сейчас { }. Кроме того, удалена поддержка обратных ссылок и добавлены следующие метасимволы: \n

Метасимвол Описание
? Соответствует предыдущему элементу ноль или один раз. Например, ab?cсоответствует только «ac» или «abc».
+ Один или несколько раз соответствует предыдущему элементу. Например, ab+cсоответствует «abc», «abbc», «abbbc» и т. Д., Но не «ac».
| Оператор выбора (также известный как чередование или объединение множества) соответствует либо выражению до, либо выражению после оператора. Например, abc|defсоответствует «abc» или «def».

Примеры:

  • [hc]?at соответствует «at», «hat» и «cat».
  • [hc]*at соответствует "at", "hat", "cat", "hhat", "chat", "hcat", "cchchat" и т. д.
  • [hc]+at соответствует "hat", "cat", "hhat", "chat", "hcat", "cchchat" и так далее, но не "at".
  • cat|dog соответствует «кот» или «собака».

Расширенные регулярные выражения POSIX часто можно использовать с современными утилитами Unix, включив флаг командной строки -E .

Классы персонажей

Класс символов - это самая основная концепция регулярного выражения после буквального совпадения. Он заставляет одну небольшую последовательность символов соответствовать большему набору символов. Например, может означать любую заглавную букву английского алфавита и может означать любую цифру. Классы символов применяются к обоим уровням POSIX. [A-Z]\d

При указании диапазона символов, например (от нижнего регистра до верхнего регистра ), настройки локали компьютера определяют содержимое по числовому порядку в кодировке символов. Они могли хранить цифры в этой последовательности, или порядок мог быть следующим: abc… zABC… Z или aAbBcC… zZ . Таким образом, стандарт POSIX определяет класс символов, который будет известен установленному процессору регулярных выражений. Эти определения приведены в следующей таблице: [a-Z]aZ

POSIX Нестандартный Perl / Tcl Vim Джава ASCII Описание
[:ascii:] \p{ASCII} [\x00-\x7F] Символы ASCII
[:alnum:] \p{Alnum} [A-Za-z0-9] Буквенно-цифровые символы
[:word:] \w \w \w [A-Za-z0-9_] Буквенно-цифровые символы плюс "_"
\W \W \W [^A-Za-z0-9_] Несловесные символы
[:alpha:] \a \p{Alpha} [A-Za-z] Буквенные символы
[:blank:] \s \p{Blank} [ \t] Пробел и табуляция
\b \< \> \b (?<=\W)(?=\w)|(?<=\w)(?=\W) Границы слов
\B (?<=\W)(?=\W)|(?<=\w)(?=\w) Несловные границы
[:cntrl:] \p{Cntrl} [\x00-\x1F\x7F] Управляющие символы
[:digit:] \d \d \p{Digit} или \d [0-9] Цифры
\D \D \D [^0-9] Нецифровые
[:graph:] \p{Graph} [\x21-\x7E] Видимые персонажи
[:lower:] \l \p{Lower} [a-z] Строчные буквы
[:print:] \p \p{Print} [\x20-\x7E] Видимые символы и пробел
[:punct:] \p{Punct} [][!"#$%&'()*+,./:;<=>?@\^_`{|}~-] Знаки препинания
[:space:] \s \_s \p{Space} или \s [ \t\r\n\v\f] Пробельные символы
\S \S \S [^ \t\r\n\v\f] Непробельные символы
[:upper:] \u \p{Upper} [A-Z] Заглавные буквы
[:xdigit:] \x \p{XDigit} [A-Fa-f0-9] Шестнадцатеричные цифры

Классы символов POSIX могут использоваться только в выражениях в квадратных скобках. Например, соответствует прописным и строчным буквам «a» и «b». [[:upper:]ab]

Некоторые инструменты понимают дополнительный класс, не относящийся к POSIX , который обычно определяется как знак подчеркивания плюс. Это отражает тот факт, что во многих языках программирования это символы, которые могут использоваться в идентификаторах. Редактор Vim дополнительно различает классы слов и заголовков слов (используя нотацию и ), поскольку во многих языках программирования символы, которые могут начинать идентификатор, не совпадают с символами, которые могут встречаться в других позициях: числа обычно исключаются, поэтому идентификатор будет выглядеть или в нотации POSIX. [:word:][:alnum:]\w\h\h\w*[[:alpha:]_][[:alnum:]_]*

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

Perl и PCRE

Из-за его выразительной силы и (относительной) простоты чтения многие другие утилиты и языки программирования приняли синтаксис, аналогичный синтаксису Perl, например, Java , JavaScript , Julia , Python , Ruby , Qt , Microsoft .NET Framework и XML. Схема . Некоторые языки и инструменты, такие как Boost и PHP, поддерживают несколько разновидностей регулярных выражений. Реализации регулярных выражений, производные от Perl, не идентичны и обычно реализуют подмножество функций, обнаруженных в Perl 5.0, выпущенном в 1994 году. Perl иногда действительно включает функции, изначально обнаруженные в других языках. Например, Perl 5.10 реализует синтаксические расширения, изначально разработанные на PCRE и Python.

Ленивое сопоставление

В Python и некоторых других реализациях (например, Java) три общих квантификатора ( *, +и ?) по умолчанию являются жадными , поскольку они соответствуют как можно большему количеству символов. Регулярное выражение ".+"(включая двойные кавычки), примененное к строке

"Ganymede," he continued, "is the largest moon in the Solar System."

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

Тем не менее, при некоторых обстоятельствах все предложение может быть сопоставлено. Оператор вопросительного знака не меняет значения оператора точки, поэтому он по-прежнему может соответствовать двойным кавычкам во входных данных. Шаблон вроде по- ".*?" EOFпрежнему будет соответствовать всему вводу, если это строка:

"Ganymede," he continued, "is the largest moon in the Solar System." EOF

Чтобы гарантировать, что двойные кавычки не могут быть частью совпадения, точку необходимо заменить (например "[^"]*"). Это будет соответствовать цитируемой части текста без дополнительных двойных кавычек. (За счет исключения возможности сопоставления фиксированного суффикса, т. Е. "Это также преобразовало ленивое совпадение в жадное совпадение, поэтому ?больше не требуется.)

Притяжательное соответствие

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

"Ganymede," he continued, "is the largest moon in the Solar System."

соответствует всей строке, регулярное выражение ".*+"вообще не соответствует , потому что .*+потребляет весь ввод, включая финал ". Таким образом, притяжательные квантификаторы наиболее полезны с классами отрицательных символов, например "[^"]*+", которые соответствуют "Ganymede,"при применении к той же строке.

Другое распространенное расширение, выполняющее ту же функцию, - это атомарная группировка, которая отключает отслеживание с возвратом для заключенной в скобки группы. Типичный синтаксис - (?> Группа) . Например, в то время как ^ (wi | w) i $ соответствует как wi, так и wii , ^ (?> Wi | w) i $ соответствует только wii, потому что движку запрещен возврат с возвратом, и попробуйте установить группу как «w».

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

Шаблоны для нерегулярных языков

Многие функции, присутствующие практически во всех современных библиотеках регулярных выражений, обеспечивают выразительность, превосходящую возможности обычных языков . Например, многие реализации позволяют группировать подвыражения с помощью круглых скобок и вызывать значение, которое они соответствуют в том же выражении ( обратные ссылки ). Это означает, что, помимо прочего, шаблон может соответствовать строкам повторяющихся слов, таких как «папа» или «WikiWiki», которыев формальной теории языканазываютсяквадратами. Шаблон для этих струн(.+)\1.

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

Однако многие инструменты, библиотеки и механизмы, которые предоставляют такие конструкции, по-прежнему используют термин регулярное выражение для своих шаблонов. Это привело к номенклатуре, в которой термин регулярное выражение имеет разные значения в теории формального языка и сопоставлении с образцом. По этой причине некоторые люди стали использовать термин регулярное выражение , регулярное выражение или просто шаблон для описания последнего. Ларри Уолл , автор языка программирования Perl, пишет в эссе о дизайне Raku :

«Регулярные выражения» […] лишь незначительно связаны с реальными регулярными выражениями. Тем не менее, этот термин вырос вместе с возможностями наших механизмов сопоставления с образцом, поэтому я не собираюсь здесь бороться с лингвистической необходимостью. Однако я обычно назову их «регулярными выражениями» (или «регулярными выражениями», когда я в англосаксонском настроении).

Утверждение Смотреть за Смотреть вперед
Положительный (? <= шаблон ) (? = шаблон )
Отрицательный (? <! шаблон ) (? ! шаблон )
Утверждения просмотра назад и вперед
в регулярных выражениях Perl

К другим функциям, отсутствующим в описании обычных языков, относятся утверждения. К ним относятся вездесущие ^ и $ , а также некоторые более сложные расширения, такие как lookaround. Они определяют окружение совпадения и не распространяются на само совпадение - функция, имеющая отношение только к варианту использования строкового поиска. Некоторые из них можно смоделировать на обычном языке, рассматривая окружение как часть языка.

Реализации и время работы

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

Самый старый и самый быстрый основан на результате в теории формального языка, который позволяет преобразовать любой недетерминированный конечный автомат (NFA) в детерминированный конечный автомат (DFA). DFA можно создать явно, а затем запускать в полученной входной строке по одному символу за раз. Построение DFA для регулярного выражения размера m требует времени и памяти O (2 m ), но его можно запустить для строки размера n за время O ( n ). Обратите внимание, что размер выражения - это размер после того, как аббревиатуры, такие как числовые квантификаторы, были расширены.

Альтернативный подход заключается в прямом моделировании NFA, по сути, построении каждого состояния DFA по запросу, а затем отбрасывании его на следующем этапе. Это сохраняет DFA неявным и позволяет избежать экспоненциальных затрат на строительство, но текущие затраты возрастают до O ( mn ). Явный подход называется алгоритмом DFA, а неявный подход - алгоритмом NFA. Добавление кеширования к алгоритму NFA часто называют алгоритмом «ленивого DFA» или просто алгоритмом DFA без каких-либо различий. Эти алгоритмы быстры, но использовать их для вызова сгруппированных подвыражений, ленивого количественного анализа и подобных функций сложно. Современные реализации включают семейство re1-re2-sregex, основанное на коде Кокса.

Третий алгоритм - сопоставление шаблона с входной строкой путем поиска с возвратом . Этот алгоритм обычно называют NFA, но эта терминология может сбивать с толку. Его время работы может быть экспоненциальным, что демонстрируют простые реализации при сопоставлении с подобными выражениями , содержащими как чередование, так и неограниченное количественное определение, и заставляют алгоритм рассматривать экспоненциально увеличивающееся количество подвариантов. Такое поведение может вызвать проблему безопасности, называемую отказом в обслуживании регулярным выражением (ReDoS). (a|aa)*b

Хотя реализации обратного отслеживания дают экспоненциальную гарантию только в худшем случае, они обеспечивают гораздо большую гибкость и выразительность. Например, любая реализация, которая позволяет использовать обратные ссылки или реализует различные расширения, представленные Perl, должна включать какой-либо вид обратного отслеживания. Некоторые реализации пытаются обеспечить лучшее из обоих алгоритмов, сначала запустив быстрый алгоритм DFA, и возвращаются к потенциально более медленному алгоритму обратного отслеживания только тогда, когда обратная ссылка встречается во время сопоставления. GNU grep (и лежащий в основе gnulib DFA) использует такую ​​стратегию.

Сублинейные алгоритмы выполнения были достигнуты с использованием алгоритмов на основе Бойера-Мура (BM) и связанных с ними методов оптимизации DFA, таких как обратное сканирование. GNU grep, который поддерживает широкий спектр синтаксисов и расширений POSIX, использует BM для предварительной фильтрации первого прохода, а затем использует неявный DFA. Wu agreementp , который реализует приблизительное сопоставление, объединяет предварительную фильтрацию в DFA в BDM (обратное сопоставление DAWG). BNDM от NR-grep расширяет технику BDM с помощью параллелизма на уровне битов Shift-Or.

Существует несколько теоретических альтернатив обратному отслеживанию для обратных ссылок, и их «показатели» более укрощены в том смысле, что они связаны только с количеством обратных ссылок, фиксированным свойством некоторых языков регулярных выражений, таких как POSIX. Один наивный метод, который дублирует NFA без возврата для каждой заметки обратной ссылки, имеет сложность времени и пространства для стога сена длиной n и k обратных ссылок в RegExp. Недавняя теоретическая работа, основанная на автоматах памяти, дает более жесткие границы на основе используемых «активных» переменных узлов и полиномиальную возможность для некоторых регулярных выражений с обратными ссылками.

Юникод

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

  • Поддерживаемая кодировка . Некоторые библиотеки регулярных выражений рассчитывают работать с определенной кодировкой вместо абстрактных символов Юникода. Многие из них требуют кодировки UTF-8 , в то время как другие могут ожидать UTF-16 или UTF-32 . Напротив, Perl и Java не зависят от кодировок, вместо этого работая с декодированными символами внутри себя.
  • Поддерживаемый диапазон Unicode . Многие механизмы регулярных выражений поддерживают только базовую многоязычную плоскость , то есть символы, которые могут быть закодированы только с помощью 16 бит. В настоящее время (по состоянию на 2016 год) только несколько механизмов регулярных выражений (например, Perl и Java) могут обрабатывать полный 21-битный диапазон Unicode.
  • Расширение конструкций, ориентированных на ASCII, до Unicode . Например, в реализациях на основе ASCII диапазоны символов формы [x-y]действительны везде, где x и y имеют кодовые точки в диапазоне [0x00,0x7F] и кодовая точка ( x ) ≤ кодовая точка ( y ). Естественное расширение таких диапазонов символов до Unicode просто изменило бы требование, чтобы конечные точки лежали в [0x00,0x7F], на требование, чтобы они лежали в [0x0000,0x10FFFF]. Однако на практике это часто не так. Некоторые реализации, такие как gawk , не позволяют диапазонам символов пересекать блоки Unicode. Диапазон вроде [0x61,0x7F] допустим, поскольку обе конечные точки попадают в блок Basic Latin, как и [0x0530,0x0560], поскольку обе конечные точки попадают в армянский блок, но диапазон вроде [0x0061,0x0532] недействителен, поскольку он включает несколько блоков Unicode. Другие движки, такие как редактор Vim , допускают пересечение блоков, но значения символов не должны быть больше 256 друг от друга.
  • Нечувствительность к регистру . Некоторые флаги нечувствительности к регистру влияют только на символы ASCII. Остальные флаги влияют на всех персонажей. Некоторые движки имеют два разных флага: один для ASCII, другой для Unicode. Также различается, какие именно символы принадлежат классам POSIX.
  • Двоюродные братья нечувствительности к регистру . Поскольку в ASCII есть разделение на регистр, нечувствительность к регистру стала логической особенностью текстового поиска. Unicode представил алфавитные сценарии без регистра, такие как Деванагари . Для них чувствительность к регистру не применяется. Для таких шрифтов, как китайский, логичным кажется другое различие: между традиционным и упрощенным. В арабских шрифтах может быть желательна нечувствительность к начальному, среднему, конечному и изолированному положению . В японском языке иногда полезно использовать нечувствительность между хираганой и катаканой .
  • Нормализация . Юникод имеет комбинированные символы . Как и в старых пишущих машинках, простые базовые символы (пробелы, знаки препинания, символы, цифры или буквы) могут сопровождаться одним или несколькими символами без пробелов (обычно диакритическими знаками, такими как знаки ударения, изменяющие буквы), чтобы сформировать один печатаемый символ; но Unicode также предоставляет ограниченный набор предварительно составленных символов, т. е. символов, которые уже включают один или несколько комбинирующих символов. Последовательность базового символа + комбинирующих символов должна совпадать с идентичным одиночным предварительно составленным символом (только некоторые из этих комбинирующих последовательностей могут быть предварительно составлены в один символ Юникода, но бесконечно много других комбинирующих последовательностей возможно в Юникоде и необходимо для различных языков. , используя один или несколько комбинирующих символов после начального базового символа; эти комбинирующие последовательности могут включать в себя базовый символ или комбинирующие символы, частично предварительно составленные, но не обязательно в каноническом порядке и не обязательно с использованием канонических предварительных составов). Процесс стандартизации последовательностей базового символа + комбинирования символов путем декомпозиции этих канонически эквивалентных последовательностей перед их переупорядочиванием в каноническом порядке (и, возможно, перекомпоновкой некоторых комбинируемых символов в ведущий базовый символ) называется нормализацией.
  • Новые коды управления . Среди прочего, введен Unicode, метки порядка байтов и маркеры направления текста. С этими кодами, возможно, придется обращаться особым образом.
  • Введение классов символов для блоков Unicode, скриптов и множества других свойств символов . Свойства блока гораздо менее полезны, чем свойства скрипта, потому что блок может иметь кодовые точки из нескольких разных скриптов, а скрипт может иметь кодовые точки из нескольких разных блоков. В Perl и java.util.regexбиблиотеки, свойства формы \p{InX}или \p{Block=X}спичечных символов в блоке X и \P{InX}или \P{Block=X}точек совпадения кода не в этом блоке. Точно так же \p{Armenian}, \p{IsArmenian}или \p{Script=Armenian}матчи любого символа армянской письменности. В общем, \p{X}соответствует любому символу с каждой бинарной собственности X или общей категории X . Так , например, \p{Lu}, \p{Uppercase_Letter}, или \p{GC=Lu}спички любой заглавной буквы. Двоичные свойства, которые не общие категории включают \p{White_Space}, \p{Alphabetic}, \p{Math}и \p{Dash}. Примеры недвоичных свойств являются \p{Bidi_Class=Right_to_Left}, \p{Word_Break=A_Letter}и \p{Numeric_Value=10}.

Использует

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

Хотя регулярные выражения могут быть полезны в поисковых системах Интернета , их обработка по всей базе данных может потреблять чрезмерные ресурсы компьютера в зависимости от сложности и структуры регулярного выражения. Хотя во многих случаях системные администраторы могут выполнять внутренние запросы на основе регулярных выражений, большинство поисковых систем не предлагают публичной поддержки регулярных выражений. Известные исключения включают Google Code Search и Exalead . Однако Google Code Search был закрыт в январе 2012 года.

Примеры

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

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

В примерах используются следующие условные обозначения.

metacharacter(s) ;; the metacharacters column specifies the regex syntax being demonstrated
=~ m//           ;; indicates a regex match operation in Perl
=~ s///          ;; indicates a regex substitution operation in Perl

Также стоит отметить, что все эти регулярные выражения имеют синтаксис, подобный Perl. Стандартные регулярные выражения POSIX отличаются.

Если не указано иное, следующие примеры соответствуют языку программирования Perl , выпуск 5.8.8, 31 января 2006 г. Это означает, что другие реализации могут не поддерживать некоторые части синтаксиса, показанного здесь (например, базовое или расширенное регулярное выражение, \( \)vs. (), или отсутствие \dвместо POSIX [:digit:] ).

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

Метасимвол (ы) Описание Пример
. Обычно соответствует любому символу, кроме новой строки.
В квадратных скобках точка буквальная.
$string1 = "Hello World\n";
if ($string1 =~ m/...../) {
  print "$string1 has length >= 5.\n";
}

Выход:

Hello World
 has length >= 5.
( ) Группирует серию элементов узора в один элемент.
Когда вы подходите шаблон внутри скобок, вы можете использовать любой из $1, $2... потом ссылаться на ранее согласованный шаблон.
$string1 = "Hello World\n";
if ($string1 =~ m/(H..).(o..)/) {
  print "We matched '$1' and '$2'.\n";
}

Выход:

We matched 'Hel' and 'o W'.
+ Один или несколько раз соответствует предыдущему элементу шаблона.
$string1 = "Hello World\n";
if ($string1 =~ m/l+/) {
  print "There are one or more consecutive letter \"l\"'s in $string1.\n";
}

Выход:

There are one or more consecutive letter "l"'s in Hello World.
? Соответствует предыдущему элементу шаблона ноль или один раз.
$string1 = "Hello World\n";
if ($string1 =~ m/H.?e/) {
  print "There is an 'H' and a 'e' separated by ";
  print "0-1 characters (e.g., He Hue Hee).\n";
}

Выход:

There is an 'H' and a 'e' separated by 0-1 characters (e.g., He Hue Hee).
? Изменяет *, +, ?или {M,N}«d регулярное выражение , которое приходит раньше , чтобы соответствовать , как несколько раз , как это возможно.
$string1 = "Hello World\n";
if ($string1 =~ m/(l.+?o)/) {
  print "The non-greedy match with 'l' followed by one or ";
  print "more characters is 'llo' rather than 'llo Wo'.\n";
}

Выход:

The non-greedy match with 'l' followed by one or more characters is 'llo' rather than 'llo Wo'.
* Соответствует предыдущему элементу шаблона ноль или более раз.
$string1 = "Hello World\n";
if ($string1 =~ m/el*o/) {
  print "There is an 'e' followed by zero to many ";
  print "'l' followed by 'o' (e.g., eo, elo, ello, elllo).\n";
}

Выход:

There is an 'e' followed by zero to many 'l' followed by 'o' (e.g., eo, elo, ello, elllo).
{M,N} Обозначает минимальное M и максимальное количество совпадений N.
N может быть опущено, а M может быть 0: {M}соответствует «точно» M раз; {M,}соответствует "не менее" M раз; {0,N}соответствует "не более" N раз.
x* y+ z?таким образом эквивалентно x{0,} y{1,} z{0,1}.
$string1 = "Hello World\n";
if ($string1 =~ m/l{1,2}/) {
  print "There exists a substring with at least 1 ";
  print "and at most 2 l's in $string1\n";
}

Выход:

There exists a substring with at least 1 and at most 2 l's in Hello World
[…] Обозначает набор возможных совпадений символов.
$string1 = "Hello World\n";
if ($string1 =~ m/[aeiou]+/) {
  print "$string1 contains one or more vowels.\n";
}

Выход:

Hello World
 contains one or more vowels.
| Разделяет альтернативные возможности.
$string1 = "Hello World\n";
if ($string1 =~ m/(Hello|Hi|Pogo)/) {
  print "$string1 contains at least one of Hello, Hi, or Pogo.";
}

Выход:

Hello World
 contains at least one of Hello, Hi, or Pogo.
\b Соответствует границе нулевой ширины между символом класса слова (см. Далее) и либо символом, не являющимся классом слова, либо ребром; такой же как

(^\w|\w$|\W\w|\w\W).

$string1 = "Hello World\n";
if ($string1 =~ m/llo\b/) {
  print "There is a word that ends with 'llo'.\n";
}

Выход:

There is a word that ends with 'llo'.
\w Соответствует буквенно-цифровому символу, включая «_»;
то же, что и [A-Za-z0-9_]в ASCII, и
[\p{Alphabetic}\p{GC=Mark}\p{GC=Decimal_Number}\p{GC=Connector_Punctuation}]

в Юникоде, где Alphabeticсвойство содержит более латинских букв, а Decimal_Numberсвойство содержит более арабских цифр.

$string1 = "Hello World\n";
if ($string1 =~ m/\w/) {
  print "There is at least one alphanumeric ";
  print "character in $string1 (A-Z, a-z, 0-9, _).\n";
}

Выход:

There is at least one alphanumeric character in Hello World
 (A-Z, a-z, 0-9, _).
\W Соответствует не буквенно-цифровому символу, за исключением "_";
то же, что и [^A-Za-z0-9_]в ASCII, и
[^\p{Alphabetic}\p{GC=Mark}\p{GC=Decimal_Number}\p{GC=Connector_Punctuation}]

в Юникоде.

$string1 = "Hello World\n";
if ($string1 =~ m/\W/) {
  print "The space between Hello and ";
  print "World is not alphanumeric.\n";
}

Выход:

The space between Hello and World is not alphanumeric.
\s Соответствует пробельному символу,
которым в ASCII являются табуляция, перевод строки, перевод страницы, возврат каретки и пробел;
в Unicode также соответствует неразрывным пробелам, следующей строке и пробелам переменной ширины (среди прочего).
$string1 = "Hello World\n";
if ($string1 =~ m/\s.*\s/) {
  print "In $string1 there are TWO whitespace characters, which may";
  print " be separated by other characters.\n";
}

Выход:

In Hello World
 there are TWO whitespace characters, which may be separated by other characters.
\S Соответствует чему угодно, кроме пробела.
$string1 = "Hello World\n";
if ($string1 =~ m/\S.*\S/) {
  print "In $string1 there are TWO non-whitespace characters, which";
  print " may be separated by other characters.\n";
}

Выход:

In Hello World
 there are TWO non-whitespace characters, which may be separated by other characters.
\d Соответствует цифре;
то же, что и [0-9]в ASCII;
в Юникоде то же самое, что \p{Digit}и \p{GC=Decimal_Number}свойство or , которое само по себе совпадает со \p{Numeric_Type=Decimal}свойством.
$string1 = "99 bottles of beer on the wall.";
if ($string1 =~ m/(\d+)/) {
  print "$1 is the first number in '$string1'\n";
}

Выход:

99 is the first number in '99 bottles of beer on the wall.'
\D Соответствует нецифровой;
то же, что и [^0-9]в ASCII или \P{Digit}в Юникоде.
$string1 = "Hello World\n";
if ($string1 =~ m/\D/) {
  print "There is at least one character in $string1";
  print " that is not a digit.\n";
}

Выход:

There is at least one character in Hello World
 that is not a digit.
^ Соответствует началу строки или строки.
$string1 = "Hello World\n";
if ($string1 =~ m/^He/) {
  print "$string1 starts with the characters 'He'.\n";
}

Выход:

Hello World
 starts with the characters 'He'.
$ Соответствует концу строки или строки.
$string1 = "Hello World\n";
if ($string1 =~ m/rld$/) {
  print "$string1 is a line or string ";
  print "that ends with 'rld'.\n";
}

Выход:

Hello World
 is a line or string that ends with 'rld'.
\A Соответствует началу строки (но не внутренней строке).
$string1 = "Hello\nWorld\n";
if ($string1 =~ m/\AH/) {
  print "$string1 is a string ";
  print "that starts with 'H'.\n";
}

Выход:

Hello
World
 is a string that starts with 'H'.
\z Соответствует концу строки (но не внутренней строке).
$string1 = "Hello\nWorld\n";
if ($string1 =~ m/d\n\z/) {
  print "$string1 is a string ";
  print "that ends with 'd\\n'.\n";
}

Выход:

Hello
World
 is a string that ends with 'd\n'.
[^…] Соответствует всем символам, кроме заключенных в квадратные скобки.
$string1 = "Hello World\n";
if ($string1 =~ m/[^abc]/) {
 print "$string1 contains a character other than ";
 print "a, b, and c.\n";
}

Выход:

Hello World
 contains a character other than a, b, and c.

Индукция

Регулярные выражения часто могут быть созданы («индуцированы» или «изучены») на основе набора примеров строк. Это известно как индукция регулярных языков и является частью общей проблемы индукции грамматики в теории вычислительного обучения . Формально, учитывая примеры строк на регулярном языке и, возможно, также данные примеры строк не на этом регулярном языке, можно создать грамматику для языка, то есть регулярное выражение, которое порождает этот язык. Не все регулярные языки могут быть индуцированы таким образом (см. Определение языка в пределе ), но многие могут. Например, набор примеров {1, 10, 100} и отрицательный набор (контрпримеров) {11, 1001, 101, 0} может быть использован, чтобы вызвать регулярное выражение 1⋅0 * (1, за которым следует ноль или более 0 с).

Смотрите также

Примечания

использованная литература

внешние ссылки