preg_match — Выполняет проверку на соответствие регулярному выражению


Содержание

Preg_match — Выполняет проверку на соответствие регулярному выражению

В php используется два языка для написания регулярных выражений PCRE и POSIX.

\d == [0-9] — любые символы от 0 до 9

\D != [^0-9] — любые символы кроме 0-9

\w == [0-9A-Za-z] — алфовитно — цифровые символы

\W != [^0-9A-Za-a] — любой символ кроме символа слово.

\s == [ \t\n\r] — символы пробел, символ табуляции, новой строки или возврата каретк.

\S != [^ \tn\r] — любые символы кроме пробела, символ табуляции, новой строки или возврата каретки

| — или

? — s?he — выдаст результат he или she тоесть буква перед знаком вопроса не является обязательной. Чтобы сделать последовательность символов (или метасимволов) необязательной, их можно сгрупировать в скобках: с помощью регулярного выражения (wo)?man можно искачть слова «man» или «woman».

+ — любое количество символов, к примеру dim+a будет dimaaaa или dimmma

* — любое воличество символов или вообше отсутствие символа К примеру dim*a Выдаст dima, dia, dimmma, dimaaaa но не dim или di

^ — начало строки

$ — конец строки

i — данный модификатор позволяет не учитывать регистр букв.

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

x — дан модификатор заставляет анализатор PCE игнорировать пробельные символы в выражениях (за исключением явно указанных как \s или в квадратных скобках) это позволяет записывать выражения более красиво.

Ограничители

preg_match_all — выполняет глобальный поиск шаблона в строке.

preg_match — выполняет проверку на соответствие регулярному выражению.

preg_quote — экранирует символы в регулярных выражениях.

preg_replace — выполняет поиск и замену по регулярному выражению.

preg_split — разбивает строку по регулярному выражению.

ereg — необходим для проверки введенных данных.

Регулярные выражения в Google Analytics

О, регулярные выражения! Как много мы о тебе наслышаны, но до сегодняшнего дня до конца толком не понимали где и как тебя применять. Настало время познакомиться с тобой — одной из самых полезных и в тоже время недооцененных функций в Google Analytics.

Начнем с предыстории. Регулярные выражения – не разработка команды Google и не отдельный язык программирования. Их истоки лежат далеко за пределами какой-то одной области. Изначально регулярные выражения стали применять в теории автоматов и теории формальных языков. А для описания этих моделей научные деятели создали собственную систему обозначений, впоследствии названную регулярными множествами (выражениями).

Широкую известность регулярные выражения получили благодаря Кену Томпсону (Kenneth Thompson) и Деннису Ритчи (Dennis Ritchie), пионерам компьютерной науки, создателям языка программирования C и операционной системы UNIX. Кен встроил их в стандартный текстовой редактор ed, тем самым внес значительный вклад в популярность регулярных выражений, ранее считавшихся инструментом для математиков и логиков.

Кен Томпсон (Kenneth Thompson) и Деннис Ритчи (Dennis Ritchie)

В 1997 году программист Филип Хейзел (Philip Hazel) создал библиотеку PCRE (Perl Compatible Regular Expressions), реализующую работу регулярных выражений на языке программирования Perl. Синтаксис регулярных выражений PCRE оказался более мощным и гибким, чем стандартных регулярных выражений POSIX. Поэтому сейчас библиотека PCRE используется во многих современных языках программирования. Самые распространенные среди них: Perl, Java, PHP, JavaScript, языки платформы .NET Framework, Python, C++, Delphi и другие.

В Google Analytics используется частичная реализация библиотеки PCRE, поскольку версия без ограничений в умелых руках может использоваться в целях нахождения уязвимостей и последующего взлома веб-сайта. Она называется RE2 и на данный момент является более предсказуемой по времени выполнения операций и требует меньше ресурсов памяти, нежели PCRE.

Так что же такое регулярные выражения?

Регулярные выражения (regular expressions, RegExp) – инструмент для поиска текстовых строк и их проверки на соответствие какому-либо шаблону, символу или слову. Результатом применения регулярного выражения является подмножество данных, отобранное согласно логике, заложенной в выражении.

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

Примеры из разных областей:

  • чтобы удалить все файлы в каталоге компьютера, которые начинаются на букву z, в командной строке операционной системы можно написать rmz*
  • для нахождения всех файлов на компьютере с расширением .pdf необходимо в строке поиска проводника ввести *.pdf
  • определить, является ли строка числом, длинной до 66 цифр, на языке программирования php: if (preg_match(«/^[0-9]<1,66>$/»,$string)) echo «ДА»;

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

Нужно вытащить данные, содержащие определенные слова, буквы или цифры? Легко! Хотите отфильтровать по значениям, начинающимся или заканчивающимся на Aa или zZ? Пожалуйста! Или просто хотите выбрать фразы, содержащие определенное количество слов или слогов? Нет проблем! Регулярные выражения — это очень мощный и гибкий инструмент, который значительно упрощает жизнь в самых разнообразных задачах.

Они присутствуют и в Excel, и в текстовых редакторах (Notepad++, EditPlus, PSPad и другие), и в Яндекс.Метрике, и даже в программе KeyCollector, знакомой многим специалистам по интернет-продвижению и применяемую для создания семантического ядра сайта.

Регулярные выражения в KeyCollector

В Google Analytics регулярные выражения используются:

Регулярные выражения. Опережающие и ретроспективные проверки

Обновл. 13 Окт 2020 |

В этом уроке мы рассмотрим группирование, обратные ссылки, опережающие и ретроспективные проверки, а также чередование с оператором ИЛИ. И, как всегда, проиллюстрируем это всё на практических примерах.

Группирование

Мы можем сгруппировать несколько символов в нашем регулярном выражении, используя круглые скобки () . Затем мы можем делать разные вещи с этой группой символов (например, добавить мультипликаторы).

Допустим, нам нужно узнать, упоминается ли какой-то конкретный человек. Его могут звать Джон Реджинальд Смит, но второе имя может присутствовать, а может и нет:

Регулярное выражение: John (Reginald )?Smith
Пример: John Reginald Smith is sometime just called John Smith .

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

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

Регулярное выражение: John (Reginald)? Smith
Пример: Проблема с этим регулярным выражением заключается в том, что оно найдёт соответствие John Reginald Smith и даже John Smith (два пробела между John и Smith), но не найдёт соответствие в John Smith. Можете ли вы понять, почему?

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

Например, нам нужно найти экземпляры IP-адресов. IP-адрес представляет собой набор из 4-х чисел (от 0 до 255), разделённых точками (например, 192.168.0.5 ):

Регулярное выражение: \b(\d<1,3>\.)<3>\d<1,3>\b
Пример: The server has an address of 10.18.0.20 and the printer has an address of 10.18.0.116 .

Это уже немного сложнее, поэтому давайте разберёмся детальнее:

\b обозначает границу слова;

здесь мы разбили IP-адрес на 3 части, состоящие из чисел от 0 до 255 + точки + последнее (4-е) число от 0 до 255;

в скобках мы обрабатываем первые 3 части IP-адреса: \d <1,3>указывает на то, что мы ищем от 1 до 3 цифр + точку, следующую за этими цифрами, которую мы не забываем экранировать ( \. ). Мы ищем ровно 3 таких последовательности, поэтому указываем мультипликатор <3>сразу за скобками;

наконец, мы ищем 4-е число, указывая \d <1,3>, и обозначаем конечную границу слова ( \b ).

Обратные ссылки

Всякий раз, когда мы сопоставляем что-либо в квадратных скобках, это значение фактически сохраняется в переменной, к которой мы можем обратиться позже в регулярном выражении. Для доступа к этой переменной мы используем escape-символ ( \ ), за которым следует цифра. Первый набор скобок обозначается как \1 , второй — \2 и т.д.

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

Регулярное выражение: (\b[A-Z]\w+\b) Smith.*\1 Smith
Пример: Harold Smith went to meet John Smith but John Smith was not there.

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

Чередование и оператор ИЛИ

При чередовании мы имеем возможность искать что-либо из указанного нами списка. Мы видели очень простой пример чередования с использованием оператора диапазона. Это позволяет нам выполнять поиск одного символа, но иногда нам может быть нужно выполнить операцию и с большим набором символов. Это делается с помощью оператора ИЛИ ( | ). Например, нам нужно найти все экземпляры dog или cat :

Регулярное выражение: dog|cat
Пример: Harold Smith has two dog s and one cat .

Мы также можем использовать несколько операторов ИЛИ для использования большего количества вариантов:

Регулярное выражение: dog|cat|bird
Пример: Harold Smith has two dog s, one cat and three bird s.

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

Регулярное выражение: (John|Harold) Smith
Пример: Harold Smith went to meet John Smith but instead bumped into Jane Smith.

Опережающие и ретроспективные проверки

Опережающие и ретроспективные проверки работают в одном из двух режимов:

позитивный — мы пытаемся найти что-то соответствующее;

негативный — мы пытаемся найти что-то несоответствующее.

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

Опережающая проверка

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

Например, допустим, что нам нужно идентифицировать числа больше 4 000, но меньше 5 000. Эта задачка выглядит на первый взгляд простой, но, на самом деле, она чуть сложнее. Обычно, первым решением, которое возникает в уме, является:

Регулярное выражение: \b4\d\d\d\b
Пример: This looks promising with 4021 but unfortunately also matches 4000 .

Теперь мы понимаем, что нам нужно искать число 4 , за которым следуют 3 цифры, и, хотя бы одна из этих цифр не должна быть нулём. Мы можем попробовать сделать следующее:

Регулярное выражение: \b4([1-9]\d\d|\d[1-9]\d|\d\d[1-9])\b
Пример: Now we will match 4010 but not 4000.

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

Теперь вы можете подумать, глядя на всё вышеизложенное, что регулярное выражение для всего лишь 4-х цифр получилось слишком громоздким. И подумайте о том, как оно увеличится, если вместо диапазона от 4 000 до 5 000 нам нужно будет искать совпадения в диапазоне от 40 000 до 50 000. Вы быстро убедитесь, что регулярное выражение выше работает, но оно не элегантно и не масштабируется.

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

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

Таким образом, мы можем решить задачу выше следующим образом:

Регулярное выражение: \b4(?!000)\d\d\d\b
Пример: Now we still match 4010 but not 4000.

Это может показаться немного запутанным, поэтому давайте разберёмся детальнее:

сначала мы ищем цифру 4 ;

когда мы находим 4 , негативная опережающая проверка возвращает true, если следующие 3 символа не являются 000 ;

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

Говоря простым языком, расшифруем регулярное выражение выше: «Мы ищем 4 , за которым не следует 3 нуля, но следуют 3 другие цифры».

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

Всё, что нам нужно сделать, это заменить ! на = .

Ретроспективная проверка

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

Синтаксис позитивной ретроспективной проверки:

Синтаксис негативной ретроспективной проверки:

Допустим, нам нужно найти экземпляры, соответствующие слову Smith , но только если это фамилия. Чтобы сделать это, мы указываем, что хотим проверить слово перед найденным значением Smith , и, если это слово начинается с заглавной буквы, мы будем считать это фамилией:

Регулярное выражение: (?
Пример: Now we won’t >Smith .

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

Заключение

Резюмируем то, что мы узнали:

() — группируем часть регулярного выражения;

\1 , \2 и т.д. — ссылаемся на соответствие, найденное группой ранее;

| — оператор ИЛИ: ищем соответствие либо правому, либо левому операнду;

Регулярные выражения для новичков

Задачи и их разборы с javascript.ru; в статье использованы комиксы xkcd.

Что такое регулярные выражения?

Если вам когда-нибудь приходилось работать с командной строкой, вы, вероятно, использовали маски имён файлов. Например, чтобы удалить все файлы в текущей директории, которые начинаются с буквы “d”, можно написать rm d* .

Регулярные выражения представляют собой похожий, но гораздо более сильный инструмент для поиска строк, проверки их на соответствие какому-либо шаблону и другой подобной работы. Англоязычное название этого инструмента — Regular Expressions или просто RegExp. Строго говоря, регулярные выражения — специальный язык для описания шаблонов строк.

Реализация этого инструмента различается в разных языках программирования, хоть и не сильно. В данной статье мы будем ориентироваться в первую очередь на реализацию Perl Compatible Regular Expressions.

Основы синтаксиса

В первую очередь стоит заметить, что любая строка сама по себе является регулярным выражением. Так, выражению Хаха , очевидно, будет соответствовать строка “Хаха” и только она. Регулярные выражения являются регистрозависимыми, поэтому строка “хаха” (с маленькой буквы) уже не будет соответствовать выражению выше.

4 октября 2020 – 1 марта 2020, Москва и онлайн, беcплатно

Однако уже здесь следует быть аккуратным — как и любой язык, регулярные выражения имеют спецсимволы, которые нужно экранировать. Вот их список: . ^ $ * + ? < >[ ] \ | ( ) . Экранирование осуществляется обычным способом — добавлением \ перед спецсимволом.

Набор символов

Предположим, мы хотим найти в тексте все междометия, обозначающие смех. Просто Хаха нам не подойдёт — ведь под него не попадут “Хехе”, “Хохо” и “Хихи”. Да и проблему с регистром первой буквы нужно как-то решить.

Здесь нам на помощь придут наборы — вместо указания конкретного символа, мы можем записать целый список, и если в исследуемой строке на указанном месте будет стоять любой из перечисленных символов, строка будет считаться подходящей. Наборы записываются в квадратных скобках — паттерну [abcd] будет соответствовать любой из символов “a”, “b”, “c” или “d”.

Внутри набора большая часть спецсимволов не нуждается в экранировании, однако использование \ перед ними не будет считаться ошибкой. По прежнему необходимо экранировать символы “\” и “^”, и, желательно, “]” (так, [][] обозначает любой из символов “]” или «[», тогда как [[]х] – исключительно последовательность “[х]”). Необычное на первый взгляд поведение регулярок с символом “]” на самом деле определяется известными правилами, но гораздо легче просто экранировать этот символ, чем их запоминать. Кроме этого, экранировать нужно символ «-», он используется для задания диапазонов (см. ниже).

Если сразу после [ записать символ ^ , то набор приобретёт обратный смысл — подходящим будет считаться любой символ кроме указанных. Так, паттерну [^xyz] соответствует любой символ, кроме, собственно, “x”, “y” или “z”.

Итак, применяя данный инструмент к нашему случаю, если мы напишем [Хх][аоие]х[аоие] , то каждая из строк “Хаха”, “хехе”, “хихи” и даже “Хохо” будут соответствовать шаблону.

Предопределённые классы символов

Для некоторых наборов, которые используются достаточно часто, существуют специальные шаблоны. Так, для описания любого пробельного символа (пробел, табуляция, перенос строки) используется \s , для цифр — \d , для символов латиницы, цифр и подчёркивания “_” — \w .

Если необходимо описать вообще любой символ, для этого используется точка — . . Если указанные классы написать с заглавной буквы ( \S , \D , \W ) то они поменяют свой смысл на противоположный — любой непробельный символ, любой символ, который не является цифрой, и любой символ кроме латиницы, цифр или подчёркивания соответственно.

Также с помощью регулярных выражений есть возможность проверить положение строки относительно остального текста. Выражение \b обозначает границу слова, \B — не границу слова, ^ — начало текста, а $ — конец. Так, по паттерну \bJava\b в строке “Java and JavaScript” найдутся первые 4 символа, а по паттерну \bJava\B — символы c 10-го по 13-й (в составе слова “JavaScript”).

Комикс про регулярные выражения с xkcd.ru

Диапазоны

У вас может возникнуть необходимость обозначить набор, в который входят буквы, например, от “б” до “ф”. Вместо того, чтобы писать [бвгдежзиклмнопрстуф] можно воспользоваться механизмом диапазонов и написать [б-ф] . Так, паттерну x[0-8A-F][0-8A-F] соответствует строка “xA6”, но не соответствует “xb9” (во-первых, из-за того, что в диапазоне указаны только заглавные буквы, во-вторых, из-за того, что 9 не входит в промежуток 0-8).

Механизм диапазонов особенно актуален для русского языка, ведь для него нет конструкции, аналогичной \w . Чтобы обозначить все буквы русского алфавита, можно использовать паттерн [а-яА-ЯёЁ] . Обратите внимание, что буква “ё” не включается в общий диапазон букв, и её нужно указывать отдельно.

Квантификаторы (указание количества повторений)

Вернёмся к нашему примеру. Что, если в “смеющемся” междометии будет больше одной гласной между буквами “х”, например “Хаахаааа”? Наша старая регулярка уже не сможет нам помочь. Здесь нам придётся воспользоваться квантификаторами.

Квантификатор Число повторений Пример Подходящие строки
Ровно n раз Ха<3>ха Хаааха
От m до n включительно Ха<2,4>ха Хаа, Хааа, Хааааха
Не менее m Ха<2,>ха Хааха, Хаааха, Хааааха и т. д.
Не более n Ха<,3>ха Хха, Хаха, Хааха, Хаааха

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

Некоторые часто используемые конструкции получили в языке регулярных выражений специальные обозначения:

Квантификатор Аналог Значение
? Ноль или одно вхождение
* Ноль или более
+ Одно или более

Таким образом, с помощью квантификаторов мы можем улучшить наш шаблон для междометий до [Хх][аоеи]+х[аоеи]* , и он сможет распознавать строки “Хааха”, “хееееех” и “Хихии”.

Ленивая квантификация

Предположим, перед нами стоит задача — найти все HTML-теги в строке

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

Это происходит из-за того, что по умолчанию квантификатор работают по т.н. жадному алгоритму — старается вернуть как можно более длинную строку, соответствующую условию. Решить проблему можно двумя способами. Первый — использовать выражение ]*> , которое запретит считать содержимым тега правую угловую скобку. Второй — объявить квантификатор не жадным, а ленивым. Делается это с помощью добавления справа к квантификатору символа ? . Т.е. для поиска всех тегов выражение обратится в .

Ревнивая квантификация

Иногда для увеличения скорости поиска (особенно в тех случаях, когда строка не соответствует регулярному выражению) можно использовать запрет алгоритму возвращаться к предыдущим шагам поиска для того, чтобы найти возможные соответствия для оставшейся части регулярного выражения. Это называется ревнивой квантификацией. Квантификатор делается ревнивым с помощью добавления к нему справа символа + . Ещё одно применение ревнивой квантификации — исключение нежелательных совпадений. Так, паттерну ab*+a в строке “ababa” будут соответствовать только первые три символа, но не символы с третьего по пятый, т.к. символ “a”, который стоит на третьей позиции, уже был использован для первого результата.

Скобочные группы

Для нашего шаблона “смеющегося” междометия осталась самая малость — учесть, что буква “х” может встречаться более одного раза, например, “Хахахахааахахооо”, а может и вовсе заканчиваться на букве “х”. Вероятно, здесь нужно применить квантификатор для группы [аиое]+х , но если мы просто напишем [аиое]х+ , то квантификатор + будет относиться только к символу “х”, а не ко всему выражению. Чтобы это исправить, выражение нужно взять в круглые скобки: ([аиое]х)+ .

Таким образом, наше выражение превращается в [Хх]([аиое]х?)+ — сначала идёт заглавная или строчная “х”, а потом произвольное ненулевое количество гласных, которые (возможно, но не обязательно) перемежаются одиночными строчными “х”. Однако это выражение решает проблему лишь частично — под это выражение попадут и такие строки, как, например, “хихахех” — кто-то может быть так и смеётся, но допущение весьма сомнительное. Очевидно, мы можем использовать набор из всех гласных лишь единожды, а потом должны как-то опираться на результат первого поиска. Но как?…

Запоминание результата поиска по группе (обратная связь)

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

Результат поиска по всем регулярному выражению: “

”.
Результат поиска по первой группе: “p”, “b”, “/b”, “i”, “/i”, “/i”, “/p”.

На результат поиска по группе можно ссылаться с помощью выражения \n , где n — цифра от 1 до 9. Например выражению (\w)(\w)\1\2 соответствуют строки “aaaa”, “abab”, но не соответствует “aabb”.

Если выражение берётся в скобки только для применения к ней квантификатора (не планируется запоминать результат поиска по этой группе), то сразу после первой скобки стоит добавить ?: , например (?:[abcd]+\w) .

С использованием этого механизма мы можем переписать наше выражение к виду [Хх]([аоие])х?(?:\1х?)* .

Перечисление

Чтобы проверить, удовлетворяет ли строка хотя бы одному из шаблонов, можно воспользоваться аналогом булевого оператора OR, который записывается с помощью символа | . Так, под шаблон Анна|Одиночество попадают строки “Анна” и “Одиночество” соответственно. Особенно удобно использовать перечисления внутри скобочных групп. Так, например (?:a|b|c|d) полностью эквивалентно [abcd] (в данном случае второй вариант предпочтительнее в силу производительности и читаемости).

С помощью этого оператора мы сможем добавить к нашему регулярному выражению для поиска междометий возможность распознавать смех вида “Ахахаах” — единственной усмешке, которая начинается с гласной: [Хх]([аоие])х?(?:\1х?)*|[Аа]х?(?:ах?)+

Полезные сервисы

Потренироваться и / или проверить своё регулярное выражение на каком-либо тексте без написания кода можно с помощью таких сервисов, как RegExr, Regexpal или Regex101. Последний, вдобавок, приводит краткие пояснения к тому, как регулярка работает.

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

RegExp Builder — визуальный конструктор функций JavaScript для работы с регулярными выражениями.

Больше инструментов можно найти в нашей подборке.

Задания для закрепления

Найдите время

Время имеет формат часы:минуты. И часы, и минуты состоят из двух цифр, пример: 09:00. Напишите регулярное выражение для поиска времени в строке: “Завтрак в 09:00”. Учтите, что “37:98” – некорректное время.

Регулярные выражения для чайников

Что такое регулярные выражения?

В народе: регэкспы, регулярки.

По-простому — это выражения для поиска и замены подстроки по шаблону.

В PHP используется название PCRE (Perl Compatible Regular Expressions —
перл совместимые регулярные выражения). В этой статье я постараюсь раскрыть
потенциал это мощного инструмента программиста. Не пытайтесь понять все сразу,
впитывайте порциями и приходите за добавкой.

Начнем

// наша строка для испытаний
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;

Если нам нужно просто узнать есть ли шаблон ‘abc’ в строке $string
мы можем набросать такой код:

echo preg_match ( «/abc/» , $string ) ;
?>

Этот код выведет ‘1’. Потому что он нашел 1 (одно) вхождение шаблона в строке.
Если шаблон в строке не обнаружен, preg_match вернет 0. При нахождении первого вхождения,
функция сразу возвращает результат! Дальнейший поиск не продолжается (см. preg_match_all)

Нахождение начала строки

Теперь мы желаем узнать, начинается ли строка с ‘abc’.
Символ начала строки в регулярках — ‘^’ (caret — знак вставки).

// тест на начало строки
if ( preg_match ( «/^abc/» , $string ) )
<
// окей, строка начинается с абс
echo ‘The string begins with abc’ ;
>
else
<
echo ‘это фэйл’ ;
>
?>

Пример выведет:
The string begins with abc

Оборачивающие слэши — разделители, содержат регуряное выражение. Это могут быть любые парные символы,
например @regex@, #regex#, /regex/ и .т.п.

Символ ^ сразу после первого разделителя указывает что выражение начинается сначала строки и НИКАК иначе.

Что делать с регистром символов (строчные-прописные)

Перепишем код, чтобы он искал строку ‘ABC’:

Скрипт вернет:
Не думаю

Все потому что поиск регистро-зависимый. Шаблон ‘abc’ не тоже самое что ‘ABC’.
Чтобы найти оба варианта, нужно использовать модификатор. В регулярных выражениях
для этого применяется модификатор ‘i’, который нужно указать за закрывающим разделителем
регулярного выражения.

if ( preg_match ( «/^ABC/i» , $string ) ) <
echo ‘Совпадение, строка начинается с abc’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Теперь скрипт найдет паттерн ‘abc’. Также теперь будут попадать под шаблон
строки вида abc, ABC, Abc, aBc, и т.п.

Позже будет рассказано подробнее о модификаторах.

Как указать в паттерне конец строки

Делается это также как и в случае с поиском начала строки.
Распространенная ошибка, допускаемя многими прогерами — использование символа $ для указания конца строки в шаблоне.
Это неверно, правильное решение — использовать утверждение \z. Посмотрите на этот код

Сниппет вернет true, потому что $ = \Z, что в свою очередь можно описать выражением (?=\z|\n\z).
Когда нам нужно получить в результате строку без «разделителей строк», $ не должен использоваться.
Также $ совпададет больше одного раза с модификатором /m, в противоположность \z. Изменим немного код,
удалим каретку (^) в начале паттерна и добавим \z в конце, также уберем зависимость от регистра модификатором /i.

// паттерн в конце строки?
if ( preg_match ( «/89 \z /i» , $string ) ) <
echo ‘Совпадение, строка заканчивается на 89’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
>> Совпадение, строка заканчивается на 89

Потому что мы определили конец строки 89. Вот так.

Мета символы

Ранее мы поэкспериментировали с простыми регулярками. Познакомились с кареткой (^) и долларом ($)/
Эти символы имееют особенное значение. Каретка (^) обозначает начало страки и доллар ($) — ее конец.
Такие символы в купе с остальными специальными называются мета символами (meta characters).

Список мета символов в регулярных выражениях:

Разберем все символы на примерах.
Если вам нужно составить шаблон в котором содержится такой символ, его необходимо экранировать (см. preg_quote)
Например шаблон: «1+1», нужно записать как-то так:

// образец
$string = ‘1+1=2’ ;

if ( preg_match ( «/^1 \+ 1/i» , $string ) ) <
// yep
echo ‘The string begins with 1+1’ ;
> else <
// nope
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
The string begins with 1+1

Потому что интерпретатор проигнорировал специальное значение символа «+», обозначенного символом экранирования «\» (бэкслэш).
Если бы мы не добавили экран к плюсу, то preg_match(«/^1+1/i», $string) не нашло бы совпадений с шаблоном.
Сам бэкслэш в свою очередь тоже нужно экранировать, если мы ищем именно этот символ «\\».

Что означают остальные мета символы

Квадратные скобки [ ] обозначают «строковой класс».

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

Или как диапазон, разделенный символом «-«:

// Ищем шаблон
echo preg_match ( «/b[aoiu]g/» , $string , $matches ) ;

Результат скрипта:
return 1

Потому что preg_match() нашел совпадение.
Этот код также найдет совпадение со строками ‘bag’ ‘bog’ ‘big’, но не с ‘beg’.
Диапазон символов [a-f] равнозначен такой записи [abcdef]. Словами формулируется так [от ‘a’ до ‘f’].
Еще раз повторю, выражения регистрозависимые, и [A-F] не тоже самое что и [a-f].

Мета символы не работыют внутри классов, поэтому их не нужно экранировать внутри квадратных скобок [. ].
Например класс [abcdef$] совпадет с символами a b c d e f $. Доллар ($) внутри класса — это простой бакс знак доллара без какого либо специального мета-свойства.

Есть правда исключения из правил:
Одна из полезных функций регулярных выражений — возможность указать шаблон НЕ совпадающий с диапазоном символов.
Чтобы это сделать, нужно использовать каретку (^) первым символом класса.
Найдем любые символы, кроме «b»:

// осуществляем поиск
preg_match ( «/[^b]/» , $string , $matches ) ;

// выведем все совпадения в цикле foreach
foreach ( $matches as $key => $value ) <
echo $key . ‘ -> ‘ . $value ;
>
?>

Результат скрипта:
0 -> a

Здесь preg_match() нашел первое совпадение с шаблоном /[^b]/.
Изменим скрипт и используем preg_match_all() для нахождения всех вхождений соответствующих шаблону /[^b]/.

// ищем ВСЕ совпадения
preg_match_all ( «/[^b]/» , $string , $matches ) ;

// выведем все совпадения в цикле foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Результат скрипта:
acefghijklmnopqrstuvwxyz0123456789

Выведет все символы, которые НЕ совпадают с шаблоном «b».

Так мы можем отфильтровать все цифры в строке:

// все символы не являющиеся цифрами от 0 до 9
preg_match_all ( «/[^0-9]/» , $string , $matches ) ;

foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Результат скрипта:
abcefghijklmnopqrstuvwxyz

Шаблон [^0-9] расшифровывается как все НЕ включая цифры от 0 до 9.

Продолжаете слушать нашу радиостанцию?
Тогда продолжим.

Метасимвол Бэкслэш (\).

Основное значение — экранирование других метасимволов.

// create a string
$string = ‘This is a [templateVar]’ ;

// try to match our pattern
preg_match_all ( «/[ \[ \] ]/» , $string , $matches ) ;

// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Здесь мы хотели найти все символы []. Без экранирования шаблон выглядел бы так — «/[[]]/»,
но мы добавили бэеслэши к скобкам [], чтобы отменить их мета-статус.
Также, к примеру, поступим с путем к файлу.
c:\dir\file.php
В паттерне будем использовать разделитель «\\».

Бэкслэш также ортодоксально используется в строках для указания специальных последовательностей: \n, \r и др.

Еще он неймспейсы разделяет!

Следующий символ «.» (точка) ака «полный стоп».

`Точка` совпадает с любым символом кроме символов разрыва строки \r или \n.
С помощью точки мы можем найти любой одиночный символ, за исключением разрыва строки.
Чтобы точка также совпадала с переводом каретки и разрывом строки, можно использовать флаг /s.

Ищем одиночный символ

$string = ‘sex at noon taxes’ ;

echo preg_match ( «/s.x/» , $string , $matches ) ;
?>

Результат скрипта:
1

Да, да preg_match() нашел одно совпадение. Пример также сработает с sax, six, sox, sux, и s x, но не совпадет с «stix».

Теперь попробуем найти \n.

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// echo the string
echo nl2br ( $string ) ;

// look for a match
echo preg_match_all ( «/ \s /» , $string , $matches ) ;

Результат скрипта:
sex
at
noon
taxes
4

preg_match_all() нашел 4 совпадения разрыва строки «\n» потому что мы использовали флаг \s. Подробнее про флаге в разделе Спец Последовательностей..

Следующий волшебный символ — звездочка (*) asterisk
Совпадает с НОЛем и/или БОЛЕЕ вхождений шаблона, находящегося перед звездочкой.
* означает опциональный шаблон — допускается что символы могут быть, а могут и отсутствовать в строке.
Так шаблон .* совпадает с любым количеством любых символов. Пример:

// create a string
$string = ‘php’ ;

// look for a match
echo preg_match ( «/ph*p/» , $string , $matches ) ;

Результат скрипта:
1

Нашлось одно совпадение. В примере это один символ «h».
Пример также совпадет также со строкой «pp» (ноль символов «h»), и «phhhp» (три символа «h»).

Добрались до мета символа символа «+»

Плюс почти тоже самое что и звездочка, за исключением того что плюс совпадает с ОДНИМ и БОЛЬШЕ символом.
Так в примере звездочка «*» совпала со строкой ‘pp’, с плюсом «+» такое не пройдет.

// create a string
$string = ‘pp’ ;


// look for a match
echo preg_match ( «/ph+p/» , $string , $matches ) ;

Результат скрипта:

Потому что ни одного символа «h».

Следубщий пациент
Мета символ «?»

Знак вопроса совпадет с НУЛЕМ или ОДНИМ вхождением символа или регулярным выражением,
указанным сразу перед ним. Полезен для указания опциональных символов (которых может и не быть).

Например, телефонный номер в Австралии: 1234-5678.

// create a string
$string = ‘12345678’ ;

// look for a match
echo preg_match ( «/1234-?5678/» , $string , $matches ) ;

Результат скрипта:
1

Потому что -? совпал 0 раз с символом «-«. Изменение строки на «1234-5678» выдаст тот же результат.

Фигурные скобки <>

Указывает на количество совпавших символов или их интервал.
Например, за фразой PHP должно следовать ТОЧНО ТРИ цифры:

// create a string
$string = ‘PHP123’ ;

// look for a match
echo preg_match ( «/PHP[0-9]<3>/» , $string , $matches ) ;

Результат скрипта:
1

Шаблон PHP 0-9(цифры от 0 до 9) <3>(три раза) совпал.

Специальные последовательности

Бэкслэш (\) используется для спец. последовательностей:

* \d — любая цифра (тоже самое что и [0-9])
* \D — любая НЕ цифра ([^0-9])
* \s — все «недосимволы» — пробелы, переводы строки, табуляция ([ \t\n\r\f\v])
* \S — все НЕ «недосимволы» ([^ \t\n\r\f\v])
* \w — все альфа-цифровые символы (буквенно-числовые) ([a-zA-Z0-9_])
* \W — все НЕ альфа-цифровые символы ([^a-zA-Z0-9_])

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

// match our pattern containing a special sequence
preg_match_all ( «/[ \w ]/» , $string , $matches ) ;

// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Результат скрипта:
abcefghijklmnopqrstuvwxyz0123456789

Мы нашли (preg_match_all) все цифры и буквы (\w) класса ( [] ).

На следующем примере мы можем убедиться, что строка не содержит чисел.

// create a string
$string = ‘2 bad for perl’ ;

// echo our string
if ( preg_match ( «/^ \d /» , $string ) ) <
echo ‘String begins with a number’ ;
> else <
echo ‘String does not begin with a number’ ;
>
?>

Метасимвол «.» (Точка, полный стоп)

Совпадает один раз с любым символом (кроме разрыва строки)

// create a string
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;

// try to match any character
if ( preg_match ( «/./» , $string ) ) <
echo ‘The string contains at least on character’ ;
> else <
echo ‘String does not contain anything’ ;
>
?>

Результат скрипта:
The string contains at least on character

Конечно, код содержит хотябы один символ.

Ранее была рассмотрена проблема нахождения символа разрыва строки, потому что «.» не совпадает с таким символом (\n).
Здесь нам на помощь придет флаг \s. Он найдет любой пробельный символ (недосимвол).

Для примера используем \n.

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// echo the string
echo nl2br ( $string ) ;

// look for a match
echo preg_match_all ( «/ \s /» , $string , $matches ) ;

Результат скрипта:
sex
at
noon
taxes
4

preg_match() нашел 4 совпадения перевода строки \n.

Теперь все вместе, хором

Более сложные выражения.
Рассмотрим оператор OR (ИЛИ).
В регулярных выражениях это символ «|» (труба, канал).

Настало время показательного «Hello World» скрипта.

// a simple string
$string = «This is a Hello World script» ;

// try to match the patterns This OR That OR There
echo preg_match ( «/^(This|That|There)/» , $string ) ;
?>

Усложним задачу: попытаемся найти одновременно Hello или Jello в строке.

// a simple string
$string = «This is a Hello World script» ;

// try to match the patterns Jello or Hello
if ( ! preg_match ( «/(Je|He)llo/» , $string ) ) <
echo ‘Pattern not found’ ;
> else <
echo ‘pattern found’ ;
>
?>

Хотя шаблон совпал, мы не видим какую имеено сроку мы нашли.
Для возвращения найденных результатов в preg_match добавляется третий параметр (&$matches):

// a simple string
$string = «This is a Hello World script» ;

// try to match the patterns Jello or Hello
// put the matches in a variable called matches
preg_match ( «/(Je|He)llo/» , $string , $matches ) ;

// loop through the array of matches and print them
foreach ( $matches as $key => $value ) <
echo $key . ‘->’ . $value . ‘
‘ ;
>
?>

Элемент массив $matches[0] содержит всю совпавшую подстроку (всегда), в примере — Hello.
Последующие элементы содержат последовательно вхождения субпаттернов «()».
$matches[1] совпадает с первым субпатерном. В примере — (Je|He)

Модификаторы и утверждения

Модификаторы изменяют поведения шаблонов регулярных выражений.

i — регистронезависимый (Ignore Case, case insensitive)
U — нежадный поиск (Make search ungreedy)
s — включая перевод строки (Includes New line)
m — мультистрока (Multiple lines)
x — Extended for comments and whitespace
e — Enables evaluation of replacement as PHP code. (preg_replace only)
S — Extra analysis of pattern

b — граница слова (Word Boundry)
B — НЕ граница слова (Not a word boundary)
A — начало шаблона (Start of subject)
Z — конец шаблона или разрыв строки (End of subject or newline at end)
z — конец шаблона (End of subject)
G — первая совпавшая позиция в шаблоне (First matching position in subject)
?>

Простой пример модификатора «i»

// create a string
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;

// try to match our pattern
if ( preg_match ( «/^ABC/i» , $string ) ) <
echo ‘Совпадение, строка начинается с abc’ ;
> else <
echo ‘Не думаю’ ;
>
?>
?>

Использование модификатора «s»

/*** create a string with new line characters ***/
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

/*** look for a match */
echo preg_match ( «/sex.at.noon/» , $string , $matches ) ;

Результат скрипта:

«.» не находит символы разрыва строки, добавим модификатор «s»
чтобы это исправить

/*** create a string with new line characters ***/
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

/*** look for a match using s modifier ***/
echo preg_match ( «/sex.at.noon/s» , $string , $matches ) ;
?>
?>

Результат скрипта:
1

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

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// look for a match
if ( preg_match ( «/^noon/im» , $string ) ) <
echo ‘Pattern Found’ ;
> else <
echo ‘Pattern not found’ ;
>
?>

Результат скрипта:
Pattern Found

Конечно регулярное выражение найдет совпадение.
Все что следует после первого символа разрыва строки отбрасывается из-за модификатора «m».

В примере используюся вместе модификаторы «i» и «m», их действие комбинируется.

«x» модификатор позволяет составлять регулярное выражение на нескольких строках,
что повышает его читабельность и позволяет добавлять комментарии внутри шаблона.

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// create our regex using comments and store the regex
// in a variable to be used with preg_match
$regex = ‘
/ # opening double quote
^ # caret means beginning of the string
noon # the pattern to match
/imx
‘ ;

// look for a match
if ( preg_match ( $regex , $string ) ) <
echo ‘Pattern Found’ ;
> else <
echo ‘Pattern not found’ ;
>
?>

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

Модификатор «e»

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

Модификатор «S»

Этот модификатор позволяет нам проанализировать строку до сопостовления с шаблонами,
которые не помечены якорями. Т.е. если шаблон не имеет начальной фиксированой позиции, как например:

Паттерн может успорить выполение шаблона в случае с множественными совпадениями.
В следующем примере появляется множественное вхождение шаблона, поэтому добавим «S».

// match our pattern containing a special sequence
preg_match_all ( «/[ \w ]/S» , $string , $matches ) ;

// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Результат скрипта:
abcefghijklmnopqrstuvwxyz01234567890

На практике модификатор используется достаточно редко.

Модификатор границы слова (word boundary) «\b»

Граница слова создается между двух «\b» модификаторов.
Это специальный «подпирающий тип модификаторов, которые позволяют указть ТОЧНОЕ совпадение.
Текст должен совпасть только с точным шаблоном заключенным в «\b»
Например, шаблон «cat» не совпадет с «catalog».

$string = ‘eregi will not be available in PHP 6’ ;

// ищем строку «lab»
if ( preg_match ( «/ \b lab \b /i» , $string ) ) <
// Совпадение
echo $string ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Не думаю

Мы пытаемся найти совпадение с паттерном «lab», которое находится внутри строки в слове «available».
Из за использования границ слов, шаблон не совпал с подстрокой.
Давайте попробуем пример, не используя модификатора границ слов.

$string = ‘eregi will remain in the computer lab’ ;

// ищем строку «lab»
if ( preg_match ( «/ \b lab \b /i» , $string ) ) <
// Совпадение
echo $string ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
eregi will remain in the computer lab

Мы видим что совпадение произошло с целым словом «lab». (\blab\b).

Модификатор \B

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

$string = ‘This lathe turns wood.’ ;

// match word boundary and non-word boundary
if ( preg_match ( «/ \B the \b /» , $string ) ) <
echo ‘Совпал шаблон «the».’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
>> Совпал шаблон «the».

Этот код сначала найдет паттерн «the». Потому что сначала указан модификатор «не граница слова»,
the находится внутри фразы и не снача ее, затем модификатор \b границы указывает что фраза должна
закончится на -the.

$string = ‘The quick brown fox jumps over the lazy dog.’ ;

// match word boundary and non-word boundary
if ( preg_match ( «/ \B the \b /» , $string ) ) <
echo ‘Совпал шаблон «the».’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Не думаю

В этот раз мы ничего не нашли, потому что «the» стоит на границе слова, а мы использовали модификатор \B.

Последний модификатор — \U

По умолчанию, PCRE «жадный» — это не значит что они съедят вашу печеньку,
а означает что шаблон совпадет с наибольшим возможным количеством символов,
попадающих под этот шаблон.

Чтобы отключить такую «жадность» регулярных выражений
— используем ограничитель «?», например «(.*?)»
— используем модификатор «\U».

Новичкам желательно использовать этот модификатор по-умолчанию, чтобы не возникало конфузов.

$string = ‘foobar foo—bar fubar’ ;

// try to match the pattern
if ( preg_match ( «/foo(.*)bar/U» , $string ) ) <
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>

Результат скрипта:
Совпадение

Другой пример — дан кусок html

Попытаемся найти все ссылки выражением preg_match_all(«/.*/s», $string),
код вернет всю искомую строку вместо трех ссылок. Добавив Нежадный модификатор, все три ссылки поотдельности.

Вычисление с preg_replace

Приветствуем на сцене модификатор «e».

Этот модификатор вычисляет заменяемый аргумент.
До этого мы не рассматривали preg_replace(), поэтому быстрый пример:

$string = ‘We will replace the word foo’ ;

// заменяем `for` на `bar`
$string = preg_replace ( «/foo/» , ‘bar’ , $string ) ;

Пример заменит в строке foo на bar. В таких простых заменах целесообразнее использовать функции обработки строк
str_replace(), которые быстрее справляются с простыми задачами, но имеют некоторые ограничения, например не поддерживают юникод.

// строка с шаблонными переменными
$string = ‘This is the <_foo_>bought to you by <_bar_>‘ ;

// создади массив со значениями переменных
$templateVars = [ «FOO» => «The PHP Way» , «BAR» => «PHPro.orG» ] ;

// заменяем и вычисляем
$string = preg_replace ( «/<_(.*?)_>/ime» , » \$ templateVars[‘$1’]» , $string ) ;

Без модификатора «е» скрипты выдаст результат:
This is a $template_vars[FOO] and this is a $template_vars[BAR]

С модификатором переменные вычислятся после замены:
This is the The PHP Way bought to you by PHPro.orG

Таким образом, модификатор «e» обладает потенциалом встроенного шаблонизатора.

Заглядывание вперед (Look Aheads)

Возможность регулярных выражений «заглянуть вперед» шаблона для определения дальнейших совпадений.
«Подглядывание вперед» бывает положительное и отрицательное

Рассмотрим сначала заглядывание вперед с отрицанием. Обозначается в шаблоне символами «?!».
Полезно при поиске шаблона, стоящего впереди от совпадения, которое нам нужно.

$string = ‘I live in the whitehouse’ ;

// try to match white not followed by house
if ( preg_match ( «/white+(?!house)/i» , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
No match is found

Потому что слово «white» следует за словом «house».
Подадим блюдо под другим соусом:

$string = ‘I live in the white house’ ;

// try to match white not followed by house
if ( preg_match ( «/white+(?!house)/i» , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Совпадение

Есть совпадение, потому что слово «white» не следует сразу же за словом «house» (как в «whitehouse»)

Позитивное/положительное заглядывание вперед «?=»

$string = ‘This is an example eg: foo’ ;

// try to match eg followed by a colon
if ( preg_match ( «/eg+(?=:)/» , $string , $match ) ) <
print_r ( $match ) ;
> else <
echo ‘Нет совпадений’ ;
>
?>

Результат скрипта:
Array < [0]=>‘eg’ >

Код ищет паттерн «eg», стоящий перед «:» двоеточием.
Но что если нам нужно найти что-то до двоеточия, например дом из предудыщего примера.
Для этого на помощь приходят «заглядывания назад».

Заглядывание назад (Look Behinds)

Позволяет просмотреть строку назад и определить наличие совпадений с шаблоном.
Также разделяется на положительное и отрицательное.
Положительное — записывается «?

$string = ‘I live in the whitehouse’ ;

// try to match house preceded by white
if ( preg_match ( «/(? , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Совпадение

Здесь мы нашли совпадение, потому что паттерн «house» сразу следует за паттерном «house».
Движок регулярных выражений «посмотрел назад» шаблона «house» и определил совпадение.

Если мы хотим, чтобы «house» НЕ следовал за словом «white»?
Используем отрицительное заглядывание назад — «?

/*** a simple string ***/
$string = ‘I live in the whitehouse’ ;

/*** try to match house preceded by white ***/
if ( preg_match ( «/(? , $string ) )
<
/*** if we find the word white, not followed by house ***/
echo ‘Совпадение’ ;
>
else
<
/*** if no match is found ***/
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
no match is found

Потому что отрицательное заглядывание не нашло шаблона «house» c шаблоном «white» в начале его.
Давайте поменяем цвет «дома», белым слишком девственный для правительственного здания.

$string = ‘I live in the bluehouse’ ;

// ищем `house` с непредшествующим `white`
if ( preg_match ( «/(? , $string ) ) <
/*** if we find the word white, not followed by house ***/
echo ‘Совпадение’ ;
> else <
/*** if no match is found ***/
echo ‘Не думаю’ ;
>
?>

Мы изменили «whitehouse» на «bluehouse» и теперь наша регулярка сработала, потому что
шаблон «white» не обнаружен перед «house».

По-умолчанию регулярки жадные, это значит что квантификаторы (какое слово страшное)
*, +, ? «пожирают» столько символов сколько могут.

/*** 4 x and 4 z chars ***/
$string = «xxxxzzzz» ;

/*** greedy regex ***/
preg_match ( «/^(.*)(z+)$/» , $string , $matches ) ;

/*** results ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Первый паттерн (.*) совпал со всеми четыремя «x» и тремя из четырех символов «z».
Сработала жадность — шаблон забрал столько символов, сколько было в искомой строке.
Проще простого помочь перестать квантификаторам быть жадными, добавив «?» к квантификатору как в примере:

/*** string of characters ***/
$string = «xxxxzzzz» ;

/*** a non greedy match ***/
preg_match ( «/^(.*?)(z+)$/» , $string , $matches ) ;

/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Теперь $matches[1] содержит четыре «x» символа и $matches[2] четыре символа «z».
Потому что квантификатор «?» изменил поведение шаблона с «взять как можно БОЛЬШЕ» на «взять как можно МЕНЬШЕ».

Чтобы сделать нежадным весь шаблон, используем модификатор «U».

/*** string of characters ***/
$string = «xxxxzzzz» ;

/*** a non greedy match ***/
preg_match ( «/^(.*)(z+)$/U» , $string , $matches ) ;

/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Результат как в предыдущем примере.

Подводные камни c ? и U

Важно заметить, что модификатор «U» не только делает поиск нежадным, он инвертирует поведение жадности квантификатора «?».
Если использовался квантификатор «?» и одновременно модификатор «U», действие «?» будет инвертировано.

/*** string of characters ***/
$string = «xxxxzzzz» ;

/*** a non greedy match ***/
preg_match ( «/^(.*?)(z+)$/U» , $string , $matches ) ;

/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Результат скрипта:
xxxxzzz
Delimiters

В этом мане было рассмотрено много регулярок и все они разделялись слэшем «/».
Иногда нам нужно находить в шаблоне слэш и когда он одновременно является разделителем регуляного выражения,
нам придется экранировать каждый встречающийся слэш, что неудобно.

Поэтому в качестве разделителя можно взять любой символ, например #, @, ^ и т.п.

/*** get the host name from a url ***/
preg_match ( ‘#^(?:http://)?([^/]+)#i’ , «http://www.phpro.org/tutorials» , $matches ) ;

/*** show the host name ***/
echo $matches [ 1 ] ;
?>

Примеры

// the string to match against
$string = ‘The cat sat on the mat’ ;

// match the beginning of the string
echo preg_match ( «/^The/» , $string ) ;

// match the end of the string
// returns 1
echo preg_match ( «/mat \z /» , $string ) ;

// match anywhere in the string
// returns 0 as no match was found for dog.
echo preg_match ( «/dog/» , $string ) ;
?>

Поиск нескольких шаблонов

// the string to match against
$string = ‘The cat sat on the matthew’ ;

// matches the letter «a» followed by zero or more «t» characters
echo preg_match ( «/at*/» , $string ) ;

// matches the letter «a» followed by a «t» character that may or may not be present
echo preg_match ( «/at?/» , $string ) ;

// matches the letter «a» followed by one or more «t» characters
echo preg_match ( «/at+/» , $string ) ;

// matches a possible letter «e» followed by one of more «w» characters anchored to the end of the string
echo preg_match ( «/e?w+ \z /» , $string ) ;

// matches the letter «a» followed by exactly two «t» characters
echo preg_match ( «/at<2>/» , $string ) ;

// matches a possible letter «e» followed by exactly two «t» characters
echo preg_match ( «/e?t<2>/» , $string ) ;

// matches a possible letter «a» followed by exactly 2 to 6 «t» chars (att attt atttttt)
echo preg_match ( «/at<2,6>/» , $string ) ;

Запомните, preg_match() возвращает только 0 или 1, и останавливается после первого успешного нахождения шаблона.

Чтобы найти все совпадения — используйте preg_match_all().

Чит Шит

\w — Any “word” character (a-z 0-9 _)
\W — Any non “word” character
\s — Whitespace (space, tab CRLF)
\S — Any non whitepsace character
\d — Digits (0-9)
\D — Any non digit character
. — (Period) – Any character except newline

^ — Start of subject (or line in multiline mode)
$ — End of subject (or line in multiline mode)
[ — Start character class definition
] — End character class definition
| — Alternates, eg (a|b) matches a or b
( — Start subpattern
) — End subpattern
\ — Escape character

n- Zero or more of n
n+ — One or more of n
n? — Zero or one occurrences of n
— n occurrences exactly
— At least n occurrences
— Between n and m occurrences (inclusive)

i — Case Insensitive
m — Multiline mode — ^ and $ match start and end of lines
s — Dotall — . class includes newline
x — Extended– comments and whitespace
e — preg_replace only – enables evaluation of replacement as PHP code
S — Extra analysis of pattern
U — Pattern is ungreedy
u — Pattern is treated as UTF-8

\b — Word boundary
\B — Not a word boundary
\A — Start of subject
\Z — End of subject or newline at end
\z — End of subject
\G — First matching position in subject

(?=) — Positive look ahead assertion foo(?=bar) matches foo when followed by bar
(?!) — Negative look ahead assertion foo(?!bar) matches foo when not followed by bar
(? ) — Once-only subpatterns (?>\d+)bar Performance enhancing when bar not present
(?(x)) — Conditional subpatterns
(?(3)foo|fu)bar — Matches foo if 3rd subpattern has matched, fu if not
(?#) — Comment (?# Pattern does x y or z)

Дополнения от меня

Posix символьные классы

Дополнительные шорткуты для шаблонов. Могут применяться только внутри классов.
Пример для поиска числа с пробелами — preg_match(«@[[:space:]\d]+@», $string)

Внутренние модификаторы шаблонов

Модификаторы m, s, x, U, X, J могут использоваться внутри шаблона.
Например (?im) установит мультистроковой регистронезивисимый метод поиска для паттерна.
Отключить внутренние модификаторы можно перечислив их через дефис, например (?im-sx)

Пример:
шаблон (?i:foo) совпадет с «FoO»

Именованный «захват»

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

Записывается: (? ), (?’name’) или (?P ).
Раньше поддерживался только такой синтаксис: (?P ). [

preg_match ( ‘/Name: (.+), Age: ( \d +)/’ , $text , $matches ) ;
preg_match ( ‘/Name: (?P .+), Age: (?P \d +)/’ , $text , $matches ) ;
?>

Результат скрипта:
array(‘Name’ => ‘строка’, ‘Age’ => ‘число’)

Замена через callback-функцию

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

\s * \w |’ ,
create_function (
‘$matches’ ,
‘return strtoupper($matches[0]);’
) ,
$line
) ;
?>

Данный код заменит все первые буквы в параграфах на заглавные.

В php >= 5.3 callback-функцию можно записать в сокращенном виде

\s * \w |’ ,
function ( $matches ) <
return strtoupper ( $matches [ 0 ] ) ;
> ,
$line
) ;
?>

Preg_match — Выполняет проверку на соответствие регулярному выражению

Начну с того, что php поддерживает два стандарта регулярных выражений: POSIX и, начиная с четвертой версии, совместимые с Perl. Первый стандарт используется и сервером Apache в mod_rewrite и в запросах MySQL (поищите слово «REGEXP» в руководстве по mysql). Второй, как ясно из названия, используется в системе perl. Два этих стандарта различаются несильно — во втором есть специальные символы, заменяющие наиболее часто используемые классы символов (например, цифры — d, а буквы и цифры — w) и специальные параметры шаблонов, позволяющие определять регистрозависимость поиска, привязку к концам строк и т.д (в функциях стандарта POSIX регистрозависимость реализована просто: есть функции ereg и ereg_eeplace, есть eregi (insensitive) и eregi_replace). В остальном же оба стандарта совместимы, а приемы написания шаблонов одинаковые.

Итак, задача системы — помимо четко заданных символов («Вася(.*)Пупкин») позволить указать пользователю поиск заданного количества заданных символов. В приведенном примере с Васей Пупкиным между словами задано любое количество любых символов. Если надо найти шесть цифр, то пишем «[0-9]<6>» (если, например, от шести до восьми цифр, тогда «[0-9]<6,8>«). Здесь разделены такие вещи как указатель набора символов и указатель необходимого количества:

Вместо набора символов может быть использовано обозначение любого символа — точка, может быть указан конкретный набор символов (поддерживаются последовательности — упоминавшиеся «0-9»). Может быть указано «кроме данного набора символов».

Указатель количества символов в официальной документации по php называется «квантификатор». Термин удобный и не несет в себе кривотолков. Итак, квантификатор может иметь как конкретное значение — либо одно фиксированное («<6>«), либо как числовой промежуток («<6,8>«), так и абстрактное «любое число, в т.ч. 0» («*»), «любое натуральное число» — от 1 до бесконечности («+»: «document[0-9]+.txt»), «либо 0, либо 1» («?»). По умолчанию квантификатор для данного набора символов равен единице («document[0-9].txt»).

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

Как всякий гибкий инструмент, регулярные выражения гибки, но не абсолютно: зона их применения ограничена. Например, если вам надо заменить в тексте одну фиксированную строку на другую, фиксированную опять же, пользуйтесь str_replace. Разработчики php слезно умоляют не пользоваться ради этого сложными функциями ereg_replace или preg_replace, ведь при их вызове происходит процесс интерпретации строки, а это серьезно потребляет ресурсы системы. К сожалению, это любимые грабли начинающих php-программистов.

Пользуйтесь функциями регулярных выражений только если вы не знаете точно, какая «там» строка. Из примеров: поисковый код , в котором из строки поиска вырезаются служебные символы и короткие слова а так же вырезаются лишние пробелы (вернее, все пробелы сжимаются: » +» заменяется на один пробел). При помощи этих функций я проверяю email пользователя, оставляющего свой отзыв. Много полезного можно сделать, но важно иметь в виду: регулярные выражения не всесильны. Например, сложную замену в большом тексте ими лучше не делать. Ведь, к примеру, комбинация «(.*)» в программном плане означает перебор всех символов текста. А если шаблон не привязан к началу или концу строки, то и сам шаблон «двигается» программой через весь текст, и получается двойной перебор, вернее перебор в квадрате. Нетрудно догадаться, что еще одна комбинация «(.*)» означает перебор в кубе, и так далее. Возведите в третью степень, скажем, 5 килобайт текста. Получается 125 000 000 000 (прописью: сто двадцать пять миллиардов операций). Конечно же, если подходить строго, там стольких операций не будет, а будет раза в четыре-восемь меньше, но важен сам порядок цифр.
POSIX.
Набор символов
. точка любой символ
[ ] квадратные скобки класс символов («любое из»)
[^ ] негативный класс символов («любое кроме»)
— тире обозначение последовательности в классе символов («[0-9]» — цифры)

Не пользуйтесь классом символов для обозначения всего лишь одного (вместо «[ ]+» вполне сойдет » +»). Не пишите в классе символов точку — это ведь любой символ, тогда другие символы в классе будут просто лишними (а в негативном классе получится отрицание всех символов).
Квантификатор

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

Если нужно указать только необходимый минимум, а максимума нет, просто ставим запятую и не пишем второе число: «<5,>» («минимум 5»). Для наиболее часто употребляемых квантификаторов есть специальные обозначения:
* «звёздочка» или знак умножения <0,>
+ плюс <1,>
? вопросительный знак

На практике такие символы используются чаще, чем фигурные скобки.
Якоря
^ привязка к началу строки
$ привязка к концу строки

Эти символы должны стоять соответственно в самом начале и в самом конце строки. Чтобы интерпретатор корректно понял символ $ в конце, желательно добавить к нему обратный слэш:

Сейчас будет сложное описание, мне оно и самому не нравится.

Эта вещь необходима для сложных запросов. Например, вам надо, чтобы в тексте были либо только маленькие буквы, либо только большие, либо только цифры. Класс символов «[a-zA-Z0-9]» не подходит. Тогда пишем такое:

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

Скобки называются subpattern (вложенный шаблон). И используются не только для сложных вариантов шаблонов, но и для гибкой замены фрагментов текста или получения их в переменную. К примеру, для печатной версии текста дублируем адреса ссылок текстом в скобках:

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

Функция ereg (и eregi), если ей указать в третьем параметре переменную, то туда будут записаны все подстроки в виде двухмерного массива [1].

Это, собственно, все. Дальше нужно только уметь составлять шаблоны. Приведу несколько примеров.

1. Переписывание адресов сервером Apache [2] (Apache работает со стандартом POSIX).

2. Поиск по базе данных
4. Проверка правильного написания email-а:

Поговорим о регулярных выражениях совместимых с Perl (Perl compatible regular expressions — PCRE).

Самое главное их преимущество перед POSIX — это возможность «жадного» поиска. Вопросительный знак в PCRE выступает еще и как минимизатор квантификатора:

Найдет минимальную подходящую строку. Вроде бы ничего особенного? Нет, это очень особенная вещь. Например, какой пример я приводил в прошлом выпуске про печатную версию текста?

То есть, внури ссылки не должно быть тегов (например «. «). Если же сделать так:

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

Все проблемы снимает жадный поиск.

Программа подберет для всех ссылок минимальную подходящую строку, т.е. только до тега «». Описывать значение такой особенности PCRE нет смыла — оно огромное. :) Идем дальше.

Цифры теперь можно обозначить не как «[0-9]», а просто «d». Не-цифры («[^0-9]») как «D». Очень удобно. Вот остальные обозначения:
w [a-z0-9]
W [^a-z0-9]
s [ ]
S [^ ]

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

i регистронезависимый поиск
m


многостроковый режим. По умолчанию PCRE ищет совпадения с шаблоном только внутри одной строки, а символы «^» и «$» совпадают только с началом и концом всего текста. Когда этот параметр установлен, «^» и «$» совпадают с началом и концом отдельных строк.
s символ «.» (точка) совпадает и с переносом строки (по умолчанию — нет)
A привязка к началу текста
E заставляет символ «$» совпадать только с концом текста. Игнорируется, если установлен парамерт m.
U Инвертирует «жадность» для каждого квантификатора (если же после квантификатора стоит «?», этот квантификатор перестает быть «жадным»).
e Строка замены интерпретитуется как PHP код.

Естественно, регистр в параметрах имеет значение. Остальное о них можно прочесть в руководстве по php.

Теперь о функциях PCRE.

Функция preg_match в отличие от ereg ищет только первое совпадение. Если нужно найти все совпадения и как-то обработать их результаты (но не напрямую через preg_replace), нужно пользоваться preg_match_all. Параметры этой функции те же.

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

Функции для работы с регулярными выражениями

preg_grep — Возвращает массив вхождений, которые соответствуют шаблону
preg_match — Выполняет проверку на соответствие регулярному выражению
preg_match_all — Выполняет глобальный поиск шаблона в строке
preg_quote — Экранирует символы в регулярных выражениях
preg_replace — Выполняет поиск и замену по регулярному выражению
preg_replace_callback — Выполняет поиск по регулярному выражению и замену
preg_split — Разбивает строку по регулярному выражению

Функция preg_grep — Возвращает массив вхождений, которые соответствуют шаблону

array preg_grep (string pattern, array input [, int flags])

preg_grep() возвращает массив, состоящий из элементов входящего массива input, которые соответствуют заданному шаблону pattern.

Параметр flags может принимать следующие значения:

PREG_GREP_INVERT
В случае, если этот флаг установлен, функция preg_grep(), возвращает те элементы массива, которые не соответствуют заданному шаблону pattern. Этот флаг доступен, начиная с PHP 4.2.0.

Начиная с PHP 4.0.4, результат, возвращаемый функцией preg_grep() использует те же индексы, что и массив исходных данных. Если такое поведение вам не подходит, примените array_values() к массиву, возвращаемому preg_grep() для реиндексации.
Пример кода:

Функция preg_match — Выполняет проверку на соответствие регулярному выражению

Ищет в заданном тексте subject совпадения с шаблоном pattern

В случае, если дополнительный параметр matches указан, он будет заполнен результатами поиска. Элемент $matches[0] будет содержать часть строки, соответствующую вхождению всего шаблона, $matches[1] — часть строки, соответствующую первой подмаске, и так далее.

flags может принимать следующие значения:

PREG_OFFSET_CAPTURE
В случае, если этот флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение. Данный флаг доступен в PHP 4.3.0 и выше.

Дополнительный параметр flags доступен начиная с PHP 4.3.0.

Поиск осуществляется слева направо, с начала строки. Дополнительный параметр offset может быть использован для указания альтернативной начальной позиции для поиска. Аналогичного результата можно достичь, заменив subject на substr()($subject, $offset). Дополнительный параметр offset доступен начиная с PHP 4.3.3.

Функция preg_match() возвращает количество найденных соответствий. Это может быть 0 (совпадения не найдены) и 1, поскольку preg_match() прекращает свою работу после первого найденного совпадения. Если необходимо найти либо сосчитать все совпадения, следует воспользоваться функцией preg_match_all(). Функция preg_match() возвращает FALSE в случае, если во время выполнения возникли какие-либо ошибки.

Подсказка: Не используйте функцию preg_match(), если необходимо проверить наличие подстроки в заданной строке. Используйте для этого strpos() либо strstr(), поскольку они выполнят эту задачу гораздо быстрее.

Результат работы примера:

Функция preg_match_all — Выполняет глобальный поиск шаблона в строке

Ищет в строке subject все совпадения с шаблоном pattern и помещает результат в массив matches в порядке, определяемом комбинацией флагов flags.

После нахождения первого соответствия последующие поиски будут осуществляться не с начала строки, а от конца последнего найденного вхождения.

Дополнительный параметр flags может комбинировать следующие значения (необходимо понимать, что использование PREG_PATTERN_ORDER одновременно с PREG_SET_ORDER бессмысленно):

PREG_PATTERN_ORDER
Если этот флаг установлен, результат будет упорядочен следующим образом: элемент $matches[0] содержит массив полных вхождений шаблона, элемент $matches[1] содержит массив вхождений первой подмаски, и так далее.

Результат работы примера:

Как мы видим, $out[0] содержит массив полных вхождений шаблона, а элемент $out[1] содержит массив подстрок, содержащихся в тегах.

PREG_SET_ORDER
Если этот флаг установлен, результат будет упорядочен следующим образом: элемент $matches[0] содержит первый набор вхождений, элемент $matches[1] содержит второй набор вхождений, и так далее.

Результат работы примера:

В таком случае массив $matches[0] содержит первый набор вхождений, а именно: элемент $matches[0][0] содержит первое вхождение всего шаблона, элемент $matches[0][1] содержит первое вхождение первой подмаски, и так далее. Аналогично массив $matches[1] содержит второй набор вхождений, и так для каждого найденного набора.

PREG_OFFSET_CAPTURE
В случае, если этот флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение. Данный флаг доступен в PHP 4.3.0 и выше.

В случае, если никакой флаг не используется, по умолчанию используется PREG_PATTERN_ORDER.

Поиск осуществляется слева направо, с начала строки. Дополнительный параметр offset может быть использован для указания альтернативной начальной позиции для поиска. Аналогичного результата можно достичь, заменив subject на substr()($subject, $offset). Дополнительный параметр offset доступен, начиная с PHP 4.3.3.

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

Функция preg_quote — Экранирует символы в регулярных выражениях

Функция preg_quote() принимает строку str и добавляет обратный слеш перед каждым служебным символом. Это бывает полезно, если в составлении шаблона участвуют строковые переменные, значение которых в процессе работы скрипта может меняться.

В случае, если дополнительный параметр delimiter указан, он будет также экранироваться. Это удобно для экранирования ограничителя, который используется в PCRE функциях. Наиболее распространенным ограничителем является символ ‘/’.

В регулярных выражениях служебными считаются следующие символы: . \\ + * ? [ ^ ] $ ( ) < >= ! | :

Функция preg_replace — Выполняет поиск и замену по регулярному выражению

Выполняет поиск в строке subject совпадений с шаблоном pattern и заменяет их на replacement. В случае, если параметр limit указан, будет произведена замена limit вхождений шаблона; в случае, если limit опущен либо равняется -1, будут заменены все вхождения шаблона.

Replacement может содержать ссылки вида \\n либо (начиная с PHP 4.0.4) $n, причем последний вариант предпочтительней. Каждая такая ссылка, будет заменена на подстроку, соответствующую n’нной заключенной в круглые скобки подмаске. n может принимать значения от 0 до 99, причем ссылка \\0 (либо $0) соответствует вхождению всего шаблона. Подмаски нумеруются слева направо, начиная с единицы.

При использовании замены по шаблону с использованием ссылок на подмаски может возникнуть ситуация, когда непосредственно за маской следует цифра. В таком случае нотация вида \\n приводит к ошибке: ссылка на первую подмаску, за которой следует цифра 1, запишется как \\11, что будет интерпретировано как ссылка на одиннадцатую подмаску. Это недоразумение можно устранить, если воспользоваться конструкцией \$<1>1, указывающей на изолированную ссылку на первую подмаску, и следующую за ней цифру 1.

Результатом работы этого примера будет:

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

Первые три параметра функции preg_replace() могут быть одномерными массивами. В случае, если массив использует ключи, при обработке массива они будут взяты в том порядке, в котором они расположены в массиве. Указание ключей в массиве для pattern и replacement не является обязательным. Если вы все же решили использовать индексы, для сопоставления шаблонов и строк, участвующих в замене, используйте функцию ksort() для каждого из массивов.

Используя ksort(), получаем желаемый результат:

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

В случае, если параметры pattern и replacement являются массивами, preg_replace() поочередно извлекает из обоих массивов по паре элементов и использует их для операции поиска и замены. Если массив replacement содержит больше элементов, чем pattern, вместо недостающих элементов для замены будут взяты пустые строки. В случае, если pattern является массивом, а replacement — строкой, по каждому элементу массива pattern будет осущесвтлен поиск и замена на pattern (шаблоном будут поочередно все элементы массива, в то время как строка замены остается фиксированной). Вариант, когда pattern является строкой, а replacement — массивом, не имеет смысла.

Модификатор /e меняет поведение функции preg_replace() таким образом, что параметр replacement после выполнения необходимых подстановок интерпретируется как PHP-код и только после этого используется для замены. Используя данный модификатор, будьте внимательны: параметр replacement должен содержать корректный PHP-код, в противном случае в строке, содержащей вызов функции preg_replace(), возникнет ошибка синтаксиса.

Этот пример выведет:

Преобразует все HTML-теги к верхнему регистру

Функция preg_replace_callback — Выполняет поиск по регулярному выражению и замену с использованием функции обратного вызова

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

Достаточно часто callback функция, кроме как в вызове preg_replace_callback(), ни в чем больше не участвует. Исходя из этих соображений, можно использовать create_function() для создания безымянной функции обратного вызова непосредственно в вызове preg_replace_callback(). Если вы используете такой подход, вся информация, связанная с заменой по регулярному выражению, будет собрана в одном месте, и пространство имен функций не будет загромождаться неиспользуемыми записями.

Функция preg_split — Разбивает строку по регулярному выражению

Возвращает массив, состоящий из подстрок заданной строки subject, которая разбита по границам, соответствующим шаблону pattern.

В случае, если параметр limit указан, функция возвращает не более, чем limit подстрок. Специальное значение limit, равное -1, подразумевает отсутствие ограничения, это весьма полезно для указания еще одного опционального параметра flags.

flags может быть произвольной комбинацией следующих флагов (соединение происходит при помощи оператора ‘|’):

PREG_SPLIT_NO_EMPTY
В случае, если этот флаг указан, функция preg_split() вернет только непустые подстроки.

PREG_SPLIT_DELIM_CAPTURE
В случае, если этот флаг указан, выражение, заключенное в круглые скобки в разделяющем шаблоне, также извлекается из заданной строки и возвращается функцией. Этот флаг был добавлен в PHP 4.0.5.

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

примеры регулярных выражений

все функции PHP для работы с регулярными выражениями

Регулярные выражения в .NET .NET Regular Expressions

Регулярные выражения предоставляют мощный, гибкий и эффективный способ обработки текста. Regular expressions provide a powerful, flexible, and efficient method for processing text. Комплексная нотация сопоставления шаблонов регулярных выражений позволяет быстро анализировать большие объемы текста для поиска определенных шаблонов символов, проверять текст на соответствие предопределенному шаблону (например, адресу электронной почты), извлекать, изменять, заменять и удалять текстовые подстроки, а также добавлять извлеченные строки в коллекцию для создания отчета. The extensive pattern-matching notation of regular expressions enables you to quickly parse large amounts of text to find specific character patterns; to validate text to ensure that it matches a predefined pattern (such as an email address); to extract, edit, replace, or delete text substrings; and to add the extracted strings to a collection in order to generate a report. Для многих приложений, которые работают со строками или анализируют большие блоки текста, регулярные выражения — незаменимый инструмент. For many applications that deal with strings or that parse large blocks of text, regular expressions are an indispensable tool.

Принцип работы регулярных выражений How Regular Expressions Work

Главный компонент обработки текста с помощью регулярных выражений — это механизм регулярных выражений, представленный в .NET объектом System.Text.RegularExpressions.Regex. The centerpiece of text processing with regular expressions is the regular expression engine, which is represented by the System.Text.RegularExpressions.Regex object in .NET. Как минимум, для обработки текста с использованием в регулярных выражений механизму регулярных выражений необходимо предоставить два следующих элемента: At a minimum, processing text using regular expressions requires that the regular expression engine be provided with the following two items of information:

Шаблон регулярного выражения для определения текста. The regular expression pattern to identify in the text.

В .NET шаблоны регулярных выражений определяются специальным синтаксисом или языком, который совместим с регулярными выражениями Perl 5 и добавляет дополнительные возможности, например сопоставление справа налево. In .NET, regular expression patterns are defined by a special syntax or language, which is compatible with Perl 5 regular expressions and adds some additional features such as right-to-left matching. Дополнительные сведения см. в разделе Элементы языка регулярных выражений. Краткий справочник. For more information, see Regular Expression Language — Quick Reference.

Текст, который будет проанализирован на соответствие шаблону регулярного выражения. The text to parse for the regular expression pattern.

Методы класса Regex позволяют выполнять следующие операции: The methods of the Regex class let you perform the following operations:

Определить, входит ли шаблон регулярного выражения во входной текст, с помощью метода Regex.IsMatch. Determine whether the regular expression pattern occurs in the input text by calling the Regex.IsMatch method. Пример использования метода IsMatch для проверки текста см. в разделе Руководство. Проверка строк на соответствие формату электронной почты. For an example that uses the IsMatch method for validating text, see How to: Verify that Strings Are in Valid Email Format.

Получить один или все экземпляры текста, соответствующего шаблону регулярного выражения с помощью метода Regex.Match или Regex.Matches. Retrieve one or all occurrences of text that matches the regular expression pattern by calling the Regex.Match or Regex.Matches method. Первый метод возвращает объект System.Text.RegularExpressions.Match, который предоставляет сведения о соответствующем тексте. The former method returns a System.Text.RegularExpressions.Match object that provides information about the matching text. Второй метод возвращает объект MatchCollection, содержащий один объект System.Text.RegularExpressions.Match для каждого соответствия, обнаруженного в обработанном тексте. The latter returns a MatchCollection object that contains one System.Text.RegularExpressions.Match object for each match found in the parsed text.

Заменить текст, соответствующий шаблону регулярного выражения, с помощью метода Regex.Replace. Replace text that matches the regular expression pattern by calling the Regex.Replace method. Примеры использования метода Replace для изменения форматов даты и удаления недопустимых символов из строки см. в разделах Руководство. Исключение недопустимых символов из строки и Руководство. Изменение форматов даты. For examples that use the Replace method to change date formats and remove invalid characters from a string, see How to: Strip Invalid Characters from a String and Example: Changing Date Formats.

Обзор объектной модели регулярных выражений см. в разделе Объектная модель регулярных выражений. For an overview of the regular expression object model, see The Regular Expression Object Model.

Дополнительные сведения о языке регулярных выражений см. в кратком справочнике по элементам языка регулярных выражений или в одной из следующих брошюр, который вы можете скачать и распечатать: For more information about the regular expression language, see Regular Expression Language — Quick Reference or download and print one of these brochures:

Примеры регулярных выражений Regular Expression Examples

Класс String содержит ряд методов для поиска и замены строк, которые можно использовать для поиска строковых литералов в длинных строках. The String class includes a number of string search and replacement methods that you can use when you want to locate literal strings in a larger string. Регулярные выражения максимально полезны, если требуется найти одну из нескольких подстрок в длинной строке или определить шаблоны в строке, как показано в следующих примерах. Regular expressions are most useful either when you want to locate one of several substrings in a larger string, or when you want to identify patterns in a string, as the following examples illustrate.

Пример 1: Замена подстрок Example 1: Replacing Substrings

Предположим, что список рассылки содержит имена, в которые иногда входит обращение (Mr., Mrs., Miss или Ms.) в дополнение к имени и фамилии. Assume that a mailing list contains names that sometimes include a title (Mr., Mrs., Miss, or Ms.) along with a first and last name. Если вы не хотите включать обращения при создании этикеток для конвертов из списка, с помощью регулярного выражения их можно удалить, как показано в следующем примере. If you do not want to include the titles when you generate envelope labels from the list, you can use a regular expression to remove the titles, as the following example illustrates.

Шаблон регулярного выражения (Mr\.? |Mrs\.? |Miss |Ms\.? ) сопоставляет все вхождения строк «Mr», «Mr.», «Mrs», «Mrs.», «Miss», «Ms» или «Ms.». The regular expression pattern (Mr\.? |Mrs\.? |Miss |Ms\.? ) matches any occurrence of «Mr «, «Mr. «, «Mrs «, «Mrs. «, «Miss «, «Ms or «Ms. «. После вызова метода Regex.Replace сопоставленная строка заменяется на String.Empty; другими словами, она удаляется из исходной строки. The call to the Regex.Replace method replaces the matched string with String.Empty; in other words, it removes it from the original string.

Пример 2: Поиск повторяющихся слов Example 2: Identifying Duplicated Words

Случайный повтор слов — это распространенная ошибка при написании текстов. Accidentally duplicating words is a common error that writers make. Регулярное выражение можно использовать для определения повторяющихся слов, как показано в следующем примере. A regular expression can be used to identify duplicated words, as the following example shows.

Шаблон регулярного выражения \b(\w+?)\s\1\b интерпретируется следующим образом: The regular expression pattern \b(\w+?)\s\1\b can be interpreted as follows:

\b Начало на границе слова. Start at a word boundary.
(\w+?) (\w+?) Соответствует одному или нескольким символам слова (как можно меньшему количеству). Match one or more word characters, but as few characters as possible. Вместе они формируют группу, к которой можно обращаться как к \1 . Together, they form a group that can be referred to as \1 .
\s Соответствует пробелу. Match a white-space character.
\1 Сопоставление подстроки, равной группе с именем \1 . Match the substring that is equal to the group named \1 .
\b Соответствует границе слова. Match a word boundary.

Метод Regex.Matches вызывается с параметрами регулярного выражения RegexOptions.IgnoreCase. The Regex.Matches method is called with regular expression options set to RegexOptions.IgnoreCase. Поэтому операция сопоставления учитывает регистр, а пример указывает, что подстрока «This this» является повтором. Therefore, the match operation is case-insensitive, and the example identifies the substring «This this» as a duplication.

Обратите внимание, что входная строка содержит подстроку «this? Note that the input string includes the substring «this? This». This». Но из-за знака пунктуации она не считается повторением. However, because of the intervening punctuation mark, it is not identified as a duplication.

Пример 3. Динамическое создание регулярного выражения с учетом языка и региональных параметров Example 3: Dynamically Building a Culture-Sensitive Regular Expression

Следующий пример демонстрирует преимущества использования регулярных выражений с гибкими возможностями глобализации .NET. The following example illustrates the power of regular expressions combined with the flexibility offered by .NET’s globalization features. В примере объект NumberFormatInfo применяется для определения формата денежных значений в текущих региональных стандартах системы. It uses the NumberFormatInfo object to determine the format of currency values in the system’s current culture. Затем эти данные используются для динамического создания регулярного выражения, которое извлекает денежные значения из текста. It then uses that information to dynamically construct a regular expression that extracts currency values from the text. Для каждого совпадения извлекается подгруппа, содержащая только числовые строки, которая преобразуется в значение Decimal, после чего рассчитывается промежуточный итог. For each match, it extracts the subgroup that contains the numeric string only, converts it to a Decimal value, and calculates a running total.

На компьютере с региональными параметрами «English — United States (en-US)» пример динамически создает регулярное выражение \$\s*[-+]?([0-9]<0,3>(,[0-9]<3>)*(\.[0-9]+)?) . On a computer whose current culture is English — United States (en-US), the example dynamically builds the regular expression \$\s*[-+]?([0-9]<0,3>(,[0-9]<3>)*(\.[0-9]+)?) . Шаблон регулярного выражения интерпретируется следующим образом: This regular expression pattern can be interpreted as follows:

\$ Выполняется поиск одного вхождения символа доллара ( $ ) во входной строке. Look for a single occurrence of the dollar symbol ( $ ) in the input string. Строка шаблона регулярного выражения содержит обратную косую черту, что говорит о том, что символ доллара интерпретируется буквально, а не как привязка регулярного выражения. The regular expression pattern string includes a backslash to indicate that the dollar symbol is to be interpreted literally rather than as a regular expression anchor. (Отдельный символ $ указывает, что механизм регулярных выражений должен начинать сопоставление с конца строки.) Чтобы правильно обработать текущий символ валюты, в примере вызывается метод Regex.Escape, который экранирует символ. (The $ symbol alone would indicate that the regular expression engine should try to begin its match at the end of a string.) To ensure that the current culture’s currency symbol is not misinterpreted as a regular expression symbol, the example calls the Regex.Escape method to escape the character.
\s* Поиск нуля или нескольких вхождений пробела. Look for zero or more occurrences of a white-space character.
[-+]? Поиск нуля или нескольких вхождений знака плюс или минус. Look for zero or one occurrence of either a positive sign or a negative sign.
([0-9]<0,3>(,[0-9]<3>)*(\.[0-9]+)?) Внешние круглые скобки вокруг этого выражения делают его захватываемой группой или частью выражения. The outer parentheses around this expression define it as a capturing group or a subexpression. Если найдено соответствие, сведения об этой части строки можно получить из второго объекта Group в объекте GroupCollection, который возвращается свойством Match.Groups. If a match is found, information about this part of the matching string can be retrieved from the second Group object in the GroupCollection object returned by the Match.Groups property. (Первый элемент в коллекции представляет все сопоставление.) (The first element in the collection represents the entire match.)
[0-9] Поиск 0-3 вхождений десятичных цифр (0-9). Look for zero to three occurrences of the decimal digits 0 through 9.
(,[0-9]<3>)* Поиск нуля или нескольких вхождений разделителя группы, за которыми следуют три десятичные цифры. Look for zero or more occurrences of a group separator followed by three decimal digits.
\. Поиск одного вхождения десятичного разделителя. Look for a single occurrence of the decimal separator.
[0-9]+ Поиск одной или нескольких десятичных цифр. Look for one or more decimal digits.
(\.[0-9]+)? Поиск нуля или одного вхождения десятичного разделителя, за которым следует по крайней мере одна десятичная цифра. Look for zero or one occurrence of the decimal separator followed by at least one decimal digit.

Если каждый из этих подшаблонов найден во входной строке, сопоставление является успешным, а объект Match с информацией о сопоставлении добавляется в объект MatchCollection. If each of these subpatterns is found in the input string, the match succeeds, and a Match object that contains information about the match is added to the MatchCollection object.

30 примеров полезных регулярных выражений

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

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

Изучение регулярных выражений ( regex ) довольно сложный процесс, особенно для начинающих, но при правильном подходе, вы освоите чрезвычайно мощный и полезный инструмент.

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

Как известно, регулярные выражения не «привязаны» к какому-то определенному языку программирования, поэтому вы можете использовать приведенные ниже примеры выражений при разработке проектов на различных языках. Например, на JavaScript, PHP или Python.

Проверка надежности пароля

Надежность пароля — довольно субъективное понятие, поэтому не существует универсального решения для проверки. Однако, приведенный выше пример регулярного выражения может стать хорошей отправной точкой, если вы не желаете придумывать выражение для проверки пароля с нуля.

Код цвета в шестнадцатеричном формате

Шестнадцатеричные коды цветов используются при веб-разработке очень часто. Это регулярное выражение может быть поможет сравнить: совпадает ли какая-либо строка с шаблоном шестнадцатеричного кода.

Проверка адреса электронной почты

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

IP-адрес (v4)

Как e-mail может использоваться для идентификации посетителя, так IP-адрес является идентификатором конкретного компьютера в сети. Приведенное регулярное выражение проверяет соответствие строки формату IP-адреса v4.

IP-адрес (v6)

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

Разделитель в больших числах

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

Добавление протокола перед гиперссылкой

Независимо от того, с каким языком вы работаете: JavaScript, Ruby или PHP, это регулярное выражение может оказаться очень полезным. С его помощью проверяется любой URL-адрес на наличие в строке протокола, и если протокол отсутствует, указанный код добавляет его в начало строки.

«Вытягиваем» домен из URL-адреса.

Как известно, любой URL-адрес состоит из нескольких частей: вначале указывается протокол (HTTP или HTTPS), иногда за ним идет субдомен, а в завершении добавляется путь к странице. Вы можете использовать это выражение, чтобы вернуть только доменное имя, исключив все остальные части адреса.

Сортировка ключевых фраз по количеству слов

Это действительно полезные выражения для пользователей Google Analytics и инструмента для веб-мастеров. Ведь с помощью них можно отсортировать ключевые фразы, используемые посетителями при поиске по количеству слов, входящих в них.

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

Поиск валидной строки Base64 в PHP

Если вы являетесь PHP-разработчиком, то иногда вам может понадобиться найти объект, закодированный в формате Base64. Указанное выше выражение может использоваться для поиска закодированных строк в любом PHP-коде.

Проверка телефонного номера

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

Проверка телефонных номеров может стать довольно сложной задачей, поэтому автор статьи рекомендует детально ознакомиться с различными вариантами решения на сайте stackoverflow.com

Для проверки российских телефонных номеров используйте следующее выражение:

Начальные и конечные пробелы

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

«Вытягиваем» HTML-код изображения

Если по какой-либо причине вам необходимо «вытянуть» HTML-код изображения прямо из кода страницы, это регулярное выражение станет для вас идеальным решением. Хотя оно может без проблем работать на стороне сервера, для фронтенд-разработчиков приоритетней будет использовать метод attr() библиотеки jQuery вместо указанного регулярного выражения.

Проверяем дату на соответствие формату DD/MM/YYYY

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

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

Совпадение строки с адресом видеоролика на YouTube

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

Если вам необходимо получить ID какого-либо видеоролика с Youtube, воспользуйтесь приведенным выше регулярным выражением. Это наилучшее выражение, подходящее для всех вариантов URL-адресов на этом видео-хостинге.

Проверка ISBN

Информация обо всех печатные изданиях, хранится в системе, известной как ISBN, которая состоит из 2 систем: ISBN-10 и ISBN-13. Неспециалисту очень сложно увидеть различия между этими системами. Однако, представленное выше регулярное выражение позволяет проверять соответствие кода ISBN сразу обоим системам: будь то ISBN-10 или ISBN-13. Код написан на PHP, поэтому это решение подходит исключительно для веб-разработчиков.

Проверка почтового индекса (Zip Code)

Автор этого регулярного выражения не только придумал его, но и еще нашел время его описать. Это выражение будет полезно вам, если вы проверяете совпадение строки со стандартным пятизначным индексом или его удлиненным вариантом, содержащим 9 знаков. Обращаем ваше внимание, что это выражение подходит только для проверки американских почтовых индексов. Для индексов других стран необходима настройка.

Для проверки российских почтовых индексов используйте следующее выражение:

Проверка правильности имени пользователя Twitter

Это небольшое регулярное выражение помогает найти имя пользователя Twitter внутри текста. Оно проверяет наличие имени в твитах по шаблону: @username .

Проверка номера кредитной карты

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

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

Поиск CSS-атрибутов

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

Этот код можно использовать когда будет необходимо «вытянуть» какое-либо CSS-правило из списка правил для какого-нибудь селектора.

Удаление комментариев в HTML

Если вам необходимо удалить все комментарии из блока HTML-кода, воспользуйтесь этим регулярным выражением. Чтобы получить желаемый результат, вы можете воспользоваться PHP-функцией preg_replace() .

Проверка на соответствие ссылке на Facebook-аккаунт

Если вам необходимо узнать у посетителя вашего сайта адрес его странички в Facebook, попробуйте это регулярное выражение. Оно поможет вам проверить правильность указанного пользователем URL. Этот код отлично подходит для проверки ссылок в этой соцсети.

Проверка версии Internet Explorer

Несмотря на то, что Microsoft выпустил новый браузер Edge, многие пользователи до сих пор пользуются Internet Explorer. Веб-разработчикам часто приходится проверять версию этого браузера, чтобы учитывать особенности разных версий при работе над своими проектами.

Вы можете использовать это регулярное выражения в JavaScript-коде чтобы узнать какая версия IE (5-11) используется.

«Вытягиваем» цену из строки

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

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

Разбираем заголовки в e-mail

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

Вместо регулярных выражений, для разбора заголовков e-mail вы можете воспользуйтесь библиотекой на PHP .

Соответствие имени файла определенному типу

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

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

Соответствие строки формату URL

Регулярное выражение может проверять URL-адреса с указанием протоколов HTTP и HTTPS на предмет соответствия синтаксису доменов TLD.

Существует простой способ проверки с использованием JavaScript RegExp .

Добавление атрибута rel=”nofollow” в теге ссылки

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

Используя приведенный код, например, совместно с PHP, вы сможете «вытянуть» код ссылок из блоков HTML-кода и добавить в каждую из них атрибут rel=”nofollow” .

Работа с media query

Вы можете разбивать строки содержащие медиа-запросы на части, состоящие из параметров и свойств. Указанное выражение может быть полезно для анализа стороннего CSS-кода. Используя его вы сможете, например, более подробно понять как устроен чужой код.

Синтаксис поисковых выражений Google

Вы можете составить свои собственные регулярные выражения для манипулирования результатами поиска по вашим запросам в поисковой системе Google. Например, знак плюс (+) добавляет дополнительные ключевые слова, а минус (-) означает, что слова должны быть проигнорированы и удалены из результатов.

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

Заключение

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

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

Регулярные выражения в Google Analytics

О, регулярные выражения! Как много мы о тебе наслышаны, но до сегодняшнего дня до конца толком не понимали где и как тебя применять. Настало время познакомиться с тобой — одной из самых полезных и в тоже время недооцененных функций в Google Analytics.

Начнем с предыстории. Регулярные выражения – не разработка команды Google и не отдельный язык программирования. Их истоки лежат далеко за пределами какой-то одной области. Изначально регулярные выражения стали применять в теории автоматов и теории формальных языков. А для описания этих моделей научные деятели создали собственную систему обозначений, впоследствии названную регулярными множествами (выражениями).

Широкую известность регулярные выражения получили благодаря Кену Томпсону (Kenneth Thompson) и Деннису Ритчи (Dennis Ritchie), пионерам компьютерной науки, создателям языка программирования C и операционной системы UNIX. Кен встроил их в стандартный текстовой редактор ed, тем самым внес значительный вклад в популярность регулярных выражений, ранее считавшихся инструментом для математиков и логиков.

Кен Томпсон (Kenneth Thompson) и Деннис Ритчи (Dennis Ritchie)

В 1997 году программист Филип Хейзел (Philip Hazel) создал библиотеку PCRE (Perl Compatible Regular Expressions), реализующую работу регулярных выражений на языке программирования Perl. Синтаксис регулярных выражений PCRE оказался более мощным и гибким, чем стандартных регулярных выражений POSIX. Поэтому сейчас библиотека PCRE используется во многих современных языках программирования. Самые распространенные среди них: Perl, Java, PHP, JavaScript, языки платформы .NET Framework, Python, C++, Delphi и другие.

В Google Analytics используется частичная реализация библиотеки PCRE, поскольку версия без ограничений в умелых руках может использоваться в целях нахождения уязвимостей и последующего взлома веб-сайта. Она называется RE2 и на данный момент является более предсказуемой по времени выполнения операций и требует меньше ресурсов памяти, нежели PCRE.

Так что же такое регулярные выражения?

Регулярные выражения (regular expressions, RegExp) – инструмент для поиска текстовых строк и их проверки на соответствие какому-либо шаблону, символу или слову. Результатом применения регулярного выражения является подмножество данных, отобранное согласно логике, заложенной в выражении.

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

Примеры из разных областей:

  • чтобы удалить все файлы в каталоге компьютера, которые начинаются на букву z, в командной строке операционной системы можно написать rmz*
  • для нахождения всех файлов на компьютере с расширением .pdf необходимо в строке поиска проводника ввести *.pdf
  • определить, является ли строка числом, длинной до 66 цифр, на языке программирования php: if (preg_match(«/^[0-9]<1,66>$/»,$string)) echo «ДА»;

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

Нужно вытащить данные, содержащие определенные слова, буквы или цифры? Легко! Хотите отфильтровать по значениям, начинающимся или заканчивающимся на Aa или zZ? Пожалуйста! Или просто хотите выбрать фразы, содержащие определенное количество слов или слогов? Нет проблем! Регулярные выражения — это очень мощный и гибкий инструмент, который значительно упрощает жизнь в самых разнообразных задачах.

Они присутствуют и в Excel, и в текстовых редакторах (Notepad++, EditPlus, PSPad и другие), и в Яндекс.Метрике, и даже в программе KeyCollector, знакомой многим специалистам по интернет-продвижению и применяемую для создания семантического ядра сайта.

Регулярные выражения в KeyCollector

В Google Analytics регулярные выражения используются:

Регулярные выражения для чайников

Что такое регулярные выражения?

В народе: регэкспы, регулярки.

По-простому — это выражения для поиска и замены подстроки по шаблону.

В PHP используется название PCRE (Perl Compatible Regular Expressions —
перл совместимые регулярные выражения). В этой статье я постараюсь раскрыть
потенциал это мощного инструмента программиста. Не пытайтесь понять все сразу,
впитывайте порциями и приходите за добавкой.

Начнем

// наша строка для испытаний
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;

Если нам нужно просто узнать есть ли шаблон ‘abc’ в строке $string
мы можем набросать такой код:

echo preg_match ( «/abc/» , $string ) ;
?>

Этот код выведет ‘1’. Потому что он нашел 1 (одно) вхождение шаблона в строке.
Если шаблон в строке не обнаружен, preg_match вернет 0. При нахождении первого вхождения,
функция сразу возвращает результат! Дальнейший поиск не продолжается (см. preg_match_all)

Нахождение начала строки

Теперь мы желаем узнать, начинается ли строка с ‘abc’.
Символ начала строки в регулярках — ‘^’ (caret — знак вставки).

// тест на начало строки
if ( preg_match ( «/^abc/» , $string ) )
<
// окей, строка начинается с абс
echo ‘The string begins with abc’ ;
>
else
<
echo ‘это фэйл’ ;
>
?>

Пример выведет:
The string begins with abc

Оборачивающие слэши — разделители, содержат регуряное выражение. Это могут быть любые парные символы,
например @regex@, #regex#, /regex/ и .т.п.

Символ ^ сразу после первого разделителя указывает что выражение начинается сначала строки и НИКАК иначе.

Что делать с регистром символов (строчные-прописные)

Перепишем код, чтобы он искал строку ‘ABC’:

Скрипт вернет:
Не думаю

Все потому что поиск регистро-зависимый. Шаблон ‘abc’ не тоже самое что ‘ABC’.
Чтобы найти оба варианта, нужно использовать модификатор. В регулярных выражениях
для этого применяется модификатор ‘i’, который нужно указать за закрывающим разделителем
регулярного выражения.

if ( preg_match ( «/^ABC/i» , $string ) ) <
echo ‘Совпадение, строка начинается с abc’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Теперь скрипт найдет паттерн ‘abc’. Также теперь будут попадать под шаблон
строки вида abc, ABC, Abc, aBc, и т.п.

Позже будет рассказано подробнее о модификаторах.

Как указать в паттерне конец строки

Делается это также как и в случае с поиском начала строки.
Распространенная ошибка, допускаемя многими прогерами — использование символа $ для указания конца строки в шаблоне.
Это неверно, правильное решение — использовать утверждение \z. Посмотрите на этот код

Сниппет вернет true, потому что $ = \Z, что в свою очередь можно описать выражением (?=\z|\n\z).
Когда нам нужно получить в результате строку без «разделителей строк», $ не должен использоваться.
Также $ совпададет больше одного раза с модификатором /m, в противоположность \z. Изменим немного код,
удалим каретку (^) в начале паттерна и добавим \z в конце, также уберем зависимость от регистра модификатором /i.

// паттерн в конце строки?
if ( preg_match ( «/89 \z /i» , $string ) ) <
echo ‘Совпадение, строка заканчивается на 89’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
>> Совпадение, строка заканчивается на 89

Потому что мы определили конец строки 89. Вот так.

Мета символы

Ранее мы поэкспериментировали с простыми регулярками. Познакомились с кареткой (^) и долларом ($)/
Эти символы имееют особенное значение. Каретка (^) обозначает начало страки и доллар ($) — ее конец.
Такие символы в купе с остальными специальными называются мета символами (meta characters).

Список мета символов в регулярных выражениях:

Разберем все символы на примерах.
Если вам нужно составить шаблон в котором содержится такой символ, его необходимо экранировать (см. preg_quote)
Например шаблон: «1+1», нужно записать как-то так:

// образец
$string = ‘1+1=2’ ;

if ( preg_match ( «/^1 \+ 1/i» , $string ) ) <
// yep
echo ‘The string begins with 1+1’ ;
> else <
// nope
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
The string begins with 1+1

Потому что интерпретатор проигнорировал специальное значение символа «+», обозначенного символом экранирования «\» (бэкслэш).
Если бы мы не добавили экран к плюсу, то preg_match(«/^1+1/i», $string) не нашло бы совпадений с шаблоном.
Сам бэкслэш в свою очередь тоже нужно экранировать, если мы ищем именно этот символ «\\».

Что означают остальные мета символы

Квадратные скобки [ ] обозначают «строковой класс».

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

Или как диапазон, разделенный символом «-«:

// Ищем шаблон
echo preg_match ( «/b[aoiu]g/» , $string , $matches ) ;

Результат скрипта:
return 1

Потому что preg_match() нашел совпадение.
Этот код также найдет совпадение со строками ‘bag’ ‘bog’ ‘big’, но не с ‘beg’.
Диапазон символов [a-f] равнозначен такой записи [abcdef]. Словами формулируется так [от ‘a’ до ‘f’].
Еще раз повторю, выражения регистрозависимые, и [A-F] не тоже самое что и [a-f].

Мета символы не работыют внутри классов, поэтому их не нужно экранировать внутри квадратных скобок [. ].
Например класс [abcdef$] совпадет с символами a b c d e f $. Доллар ($) внутри класса — это простой бакс знак доллара без какого либо специального мета-свойства.

Есть правда исключения из правил:
Одна из полезных функций регулярных выражений — возможность указать шаблон НЕ совпадающий с диапазоном символов.
Чтобы это сделать, нужно использовать каретку (^) первым символом класса.
Найдем любые символы, кроме «b»:

// осуществляем поиск
preg_match ( «/[^b]/» , $string , $matches ) ;

// выведем все совпадения в цикле foreach
foreach ( $matches as $key => $value ) <
echo $key . ‘ -> ‘ . $value ;
>
?>

Результат скрипта:
0 -> a

Здесь preg_match() нашел первое совпадение с шаблоном /[^b]/.
Изменим скрипт и используем preg_match_all() для нахождения всех вхождений соответствующих шаблону /[^b]/.

// ищем ВСЕ совпадения
preg_match_all ( «/[^b]/» , $string , $matches ) ;

// выведем все совпадения в цикле foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Результат скрипта:
acefghijklmnopqrstuvwxyz0123456789

Выведет все символы, которые НЕ совпадают с шаблоном «b».

Так мы можем отфильтровать все цифры в строке:

// все символы не являющиеся цифрами от 0 до 9
preg_match_all ( «/[^0-9]/» , $string , $matches ) ;

foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>


Результат скрипта:
abcefghijklmnopqrstuvwxyz

Шаблон [^0-9] расшифровывается как все НЕ включая цифры от 0 до 9.

Продолжаете слушать нашу радиостанцию?
Тогда продолжим.

Метасимвол Бэкслэш (\).

Основное значение — экранирование других метасимволов.

// create a string
$string = ‘This is a [templateVar]’ ;

// try to match our pattern
preg_match_all ( «/[ \[ \] ]/» , $string , $matches ) ;

// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Здесь мы хотели найти все символы []. Без экранирования шаблон выглядел бы так — «/[[]]/»,
но мы добавили бэеслэши к скобкам [], чтобы отменить их мета-статус.
Также, к примеру, поступим с путем к файлу.
c:\dir\file.php
В паттерне будем использовать разделитель «\\».

Бэкслэш также ортодоксально используется в строках для указания специальных последовательностей: \n, \r и др.

Еще он неймспейсы разделяет!

Следующий символ «.» (точка) ака «полный стоп».

`Точка` совпадает с любым символом кроме символов разрыва строки \r или \n.
С помощью точки мы можем найти любой одиночный символ, за исключением разрыва строки.
Чтобы точка также совпадала с переводом каретки и разрывом строки, можно использовать флаг /s.

Ищем одиночный символ

$string = ‘sex at noon taxes’ ;

echo preg_match ( «/s.x/» , $string , $matches ) ;
?>

Результат скрипта:
1

Да, да preg_match() нашел одно совпадение. Пример также сработает с sax, six, sox, sux, и s x, но не совпадет с «stix».

Теперь попробуем найти \n.

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// echo the string
echo nl2br ( $string ) ;

// look for a match
echo preg_match_all ( «/ \s /» , $string , $matches ) ;

Результат скрипта:
sex
at
noon
taxes
4

preg_match_all() нашел 4 совпадения разрыва строки «\n» потому что мы использовали флаг \s. Подробнее про флаге в разделе Спец Последовательностей..

Следующий волшебный символ — звездочка (*) asterisk
Совпадает с НОЛем и/или БОЛЕЕ вхождений шаблона, находящегося перед звездочкой.
* означает опциональный шаблон — допускается что символы могут быть, а могут и отсутствовать в строке.
Так шаблон .* совпадает с любым количеством любых символов. Пример:

// create a string
$string = ‘php’ ;

// look for a match
echo preg_match ( «/ph*p/» , $string , $matches ) ;

Результат скрипта:
1

Нашлось одно совпадение. В примере это один символ «h».
Пример также совпадет также со строкой «pp» (ноль символов «h»), и «phhhp» (три символа «h»).

Добрались до мета символа символа «+»

Плюс почти тоже самое что и звездочка, за исключением того что плюс совпадает с ОДНИМ и БОЛЬШЕ символом.
Так в примере звездочка «*» совпала со строкой ‘pp’, с плюсом «+» такое не пройдет.

// create a string
$string = ‘pp’ ;

// look for a match
echo preg_match ( «/ph+p/» , $string , $matches ) ;

Результат скрипта:

Потому что ни одного символа «h».

Следубщий пациент
Мета символ «?»

Знак вопроса совпадет с НУЛЕМ или ОДНИМ вхождением символа или регулярным выражением,
указанным сразу перед ним. Полезен для указания опциональных символов (которых может и не быть).

Например, телефонный номер в Австралии: 1234-5678.

// create a string
$string = ‘12345678’ ;

// look for a match
echo preg_match ( «/1234-?5678/» , $string , $matches ) ;

Результат скрипта:
1

Потому что -? совпал 0 раз с символом «-«. Изменение строки на «1234-5678» выдаст тот же результат.

Фигурные скобки <>

Указывает на количество совпавших символов или их интервал.
Например, за фразой PHP должно следовать ТОЧНО ТРИ цифры:

// create a string
$string = ‘PHP123’ ;

// look for a match
echo preg_match ( «/PHP[0-9]<3>/» , $string , $matches ) ;

Результат скрипта:
1

Шаблон PHP 0-9(цифры от 0 до 9) <3>(три раза) совпал.

Специальные последовательности

Бэкслэш (\) используется для спец. последовательностей:

* \d — любая цифра (тоже самое что и [0-9])
* \D — любая НЕ цифра ([^0-9])
* \s — все «недосимволы» — пробелы, переводы строки, табуляция ([ \t\n\r\f\v])
* \S — все НЕ «недосимволы» ([^ \t\n\r\f\v])
* \w — все альфа-цифровые символы (буквенно-числовые) ([a-zA-Z0-9_])
* \W — все НЕ альфа-цифровые символы ([^a-zA-Z0-9_])

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

// match our pattern containing a special sequence
preg_match_all ( «/[ \w ]/» , $string , $matches ) ;

// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Результат скрипта:
abcefghijklmnopqrstuvwxyz0123456789

Мы нашли (preg_match_all) все цифры и буквы (\w) класса ( [] ).

На следующем примере мы можем убедиться, что строка не содержит чисел.

// create a string
$string = ‘2 bad for perl’ ;

// echo our string
if ( preg_match ( «/^ \d /» , $string ) ) <
echo ‘String begins with a number’ ;
> else <
echo ‘String does not begin with a number’ ;
>
?>

Метасимвол «.» (Точка, полный стоп)

Совпадает один раз с любым символом (кроме разрыва строки)

// create a string
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;

// try to match any character
if ( preg_match ( «/./» , $string ) ) <
echo ‘The string contains at least on character’ ;
> else <
echo ‘String does not contain anything’ ;
>
?>

Результат скрипта:
The string contains at least on character

Конечно, код содержит хотябы один символ.

Ранее была рассмотрена проблема нахождения символа разрыва строки, потому что «.» не совпадает с таким символом (\n).
Здесь нам на помощь придет флаг \s. Он найдет любой пробельный символ (недосимвол).

Для примера используем \n.

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// echo the string
echo nl2br ( $string ) ;

// look for a match
echo preg_match_all ( «/ \s /» , $string , $matches ) ;

Результат скрипта:
sex
at
noon
taxes
4

preg_match() нашел 4 совпадения перевода строки \n.

Теперь все вместе, хором

Более сложные выражения.
Рассмотрим оператор OR (ИЛИ).
В регулярных выражениях это символ «|» (труба, канал).

Настало время показательного «Hello World» скрипта.

// a simple string
$string = «This is a Hello World script» ;

// try to match the patterns This OR That OR There
echo preg_match ( «/^(This|That|There)/» , $string ) ;
?>

Усложним задачу: попытаемся найти одновременно Hello или Jello в строке.

// a simple string
$string = «This is a Hello World script» ;

// try to match the patterns Jello or Hello
if ( ! preg_match ( «/(Je|He)llo/» , $string ) ) <
echo ‘Pattern not found’ ;
> else <
echo ‘pattern found’ ;
>
?>

Хотя шаблон совпал, мы не видим какую имеено сроку мы нашли.
Для возвращения найденных результатов в preg_match добавляется третий параметр (&$matches):

// a simple string
$string = «This is a Hello World script» ;

// try to match the patterns Jello or Hello
// put the matches in a variable called matches
preg_match ( «/(Je|He)llo/» , $string , $matches ) ;

// loop through the array of matches and print them
foreach ( $matches as $key => $value ) <
echo $key . ‘->’ . $value . ‘
‘ ;
>
?>

Элемент массив $matches[0] содержит всю совпавшую подстроку (всегда), в примере — Hello.
Последующие элементы содержат последовательно вхождения субпаттернов «()».
$matches[1] совпадает с первым субпатерном. В примере — (Je|He)

Модификаторы и утверждения

Модификаторы изменяют поведения шаблонов регулярных выражений.

i — регистронезависимый (Ignore Case, case insensitive)
U — нежадный поиск (Make search ungreedy)
s — включая перевод строки (Includes New line)
m — мультистрока (Multiple lines)
x — Extended for comments and whitespace
e — Enables evaluation of replacement as PHP code. (preg_replace only)
S — Extra analysis of pattern

b — граница слова (Word Boundry)
B — НЕ граница слова (Not a word boundary)
A — начало шаблона (Start of subject)
Z — конец шаблона или разрыв строки (End of subject or newline at end)
z — конец шаблона (End of subject)
G — первая совпавшая позиция в шаблоне (First matching position in subject)
?>

Простой пример модификатора «i»

// create a string
$string = ‘abcdefghijklmnopqrstuvwxyz0123456789’ ;

// try to match our pattern
if ( preg_match ( «/^ABC/i» , $string ) ) <
echo ‘Совпадение, строка начинается с abc’ ;
> else <
echo ‘Не думаю’ ;
>
?>
?>

Использование модификатора «s»

/*** create a string with new line characters ***/
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

/*** look for a match */
echo preg_match ( «/sex.at.noon/» , $string , $matches ) ;

Результат скрипта:

«.» не находит символы разрыва строки, добавим модификатор «s»
чтобы это исправить

/*** create a string with new line characters ***/
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

/*** look for a match using s modifier ***/
echo preg_match ( «/sex.at.noon/s» , $string , $matches ) ;
?>
?>

Результат скрипта:
1

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

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// look for a match
if ( preg_match ( «/^noon/im» , $string ) ) <
echo ‘Pattern Found’ ;
> else <
echo ‘Pattern not found’ ;
>
?>

Результат скрипта:
Pattern Found

Конечно регулярное выражение найдет совпадение.
Все что следует после первого символа разрыва строки отбрасывается из-за модификатора «m».

В примере используюся вместе модификаторы «i» и «m», их действие комбинируется.

«x» модификатор позволяет составлять регулярное выражение на нескольких строках,
что повышает его читабельность и позволяет добавлять комментарии внутри шаблона.

// create a string
$string = ‘sex’ . » \n » . ‘at’ . » \n » . ‘noon’ . » \n » . ‘taxes’ . » \n » ;

// create our regex using comments and store the regex
// in a variable to be used with preg_match
$regex = ‘
/ # opening double quote
^ # caret means beginning of the string
noon # the pattern to match
/imx
‘ ;

// look for a match
if ( preg_match ( $regex , $string ) ) <
echo ‘Pattern Found’ ;
> else <
echo ‘Pattern not found’ ;
>
?>

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

Модификатор «e»

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

Модификатор «S»

Этот модификатор позволяет нам проанализировать строку до сопостовления с шаблонами,
которые не помечены якорями. Т.е. если шаблон не имеет начальной фиксированой позиции, как например:

Паттерн может успорить выполение шаблона в случае с множественными совпадениями.
В следующем примере появляется множественное вхождение шаблона, поэтому добавим «S».

// match our pattern containing a special sequence
preg_match_all ( «/[ \w ]/S» , $string , $matches ) ;

// loop through the matches with foreach
foreach ( $matches [ 0 ] as $value ) <
echo $value ;
>
?>

Результат скрипта:
abcefghijklmnopqrstuvwxyz01234567890

На практике модификатор используется достаточно редко.

Модификатор границы слова (word boundary) «\b»

Граница слова создается между двух «\b» модификаторов.
Это специальный «подпирающий тип модификаторов, которые позволяют указть ТОЧНОЕ совпадение.
Текст должен совпасть только с точным шаблоном заключенным в «\b»
Например, шаблон «cat» не совпадет с «catalog».

$string = ‘eregi will not be available in PHP 6’ ;

// ищем строку «lab»
if ( preg_match ( «/ \b lab \b /i» , $string ) ) <
// Совпадение
echo $string ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Не думаю

Мы пытаемся найти совпадение с паттерном «lab», которое находится внутри строки в слове «available».
Из за использования границ слов, шаблон не совпал с подстрокой.
Давайте попробуем пример, не используя модификатора границ слов.

$string = ‘eregi will remain in the computer lab’ ;

// ищем строку «lab»
if ( preg_match ( «/ \b lab \b /i» , $string ) ) <
// Совпадение
echo $string ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
eregi will remain in the computer lab

Мы видим что совпадение произошло с целым словом «lab». (\blab\b).

Модификатор \B

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

$string = ‘This lathe turns wood.’ ;

// match word boundary and non-word boundary
if ( preg_match ( «/ \B the \b /» , $string ) ) <
echo ‘Совпал шаблон «the».’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
>> Совпал шаблон «the».

Этот код сначала найдет паттерн «the». Потому что сначала указан модификатор «не граница слова»,
the находится внутри фразы и не снача ее, затем модификатор \b границы указывает что фраза должна
закончится на -the.

$string = ‘The quick brown fox jumps over the lazy dog.’ ;

// match word boundary and non-word boundary
if ( preg_match ( «/ \B the \b /» , $string ) ) <
echo ‘Совпал шаблон «the».’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Не думаю

В этот раз мы ничего не нашли, потому что «the» стоит на границе слова, а мы использовали модификатор \B.

Последний модификатор — \U

По умолчанию, PCRE «жадный» — это не значит что они съедят вашу печеньку,
а означает что шаблон совпадет с наибольшим возможным количеством символов,
попадающих под этот шаблон.

Чтобы отключить такую «жадность» регулярных выражений
— используем ограничитель «?», например «(.*?)»
— используем модификатор «\U».

Новичкам желательно использовать этот модификатор по-умолчанию, чтобы не возникало конфузов.

$string = ‘foobar foo—bar fubar’ ;

// try to match the pattern
if ( preg_match ( «/foo(.*)bar/U» , $string ) ) <
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>

Результат скрипта:
Совпадение

Другой пример — дан кусок html

Попытаемся найти все ссылки выражением preg_match_all(«/.*/s», $string),
код вернет всю искомую строку вместо трех ссылок. Добавив Нежадный модификатор, все три ссылки поотдельности.

Вычисление с preg_replace

Приветствуем на сцене модификатор «e».

Этот модификатор вычисляет заменяемый аргумент.
До этого мы не рассматривали preg_replace(), поэтому быстрый пример:

$string = ‘We will replace the word foo’ ;

// заменяем `for` на `bar`
$string = preg_replace ( «/foo/» , ‘bar’ , $string ) ;

Пример заменит в строке foo на bar. В таких простых заменах целесообразнее использовать функции обработки строк
str_replace(), которые быстрее справляются с простыми задачами, но имеют некоторые ограничения, например не поддерживают юникод.

// строка с шаблонными переменными
$string = ‘This is the <_foo_>bought to you by <_bar_>‘ ;

// создади массив со значениями переменных
$templateVars = [ «FOO» => «The PHP Way» , «BAR» => «PHPro.orG» ] ;

// заменяем и вычисляем
$string = preg_replace ( «/<_(.*?)_>/ime» , » \$ templateVars[‘$1’]» , $string ) ;

Без модификатора «е» скрипты выдаст результат:
This is a $template_vars[FOO] and this is a $template_vars[BAR]

С модификатором переменные вычислятся после замены:
This is the The PHP Way bought to you by PHPro.orG

Таким образом, модификатор «e» обладает потенциалом встроенного шаблонизатора.

Заглядывание вперед (Look Aheads)

Возможность регулярных выражений «заглянуть вперед» шаблона для определения дальнейших совпадений.
«Подглядывание вперед» бывает положительное и отрицательное

Рассмотрим сначала заглядывание вперед с отрицанием. Обозначается в шаблоне символами «?!».
Полезно при поиске шаблона, стоящего впереди от совпадения, которое нам нужно.

$string = ‘I live in the whitehouse’ ;

// try to match white not followed by house
if ( preg_match ( «/white+(?!house)/i» , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
No match is found

Потому что слово «white» следует за словом «house».
Подадим блюдо под другим соусом:

$string = ‘I live in the white house’ ;

// try to match white not followed by house
if ( preg_match ( «/white+(?!house)/i» , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Совпадение

Есть совпадение, потому что слово «white» не следует сразу же за словом «house» (как в «whitehouse»)

Позитивное/положительное заглядывание вперед «?=»

$string = ‘This is an example eg: foo’ ;

// try to match eg followed by a colon
if ( preg_match ( «/eg+(?=:)/» , $string , $match ) ) <
print_r ( $match ) ;
> else <
echo ‘Нет совпадений’ ;
>
?>

Результат скрипта:
Array < [0]=>‘eg’ >

Код ищет паттерн «eg», стоящий перед «:» двоеточием.
Но что если нам нужно найти что-то до двоеточия, например дом из предудыщего примера.
Для этого на помощь приходят «заглядывания назад».

Заглядывание назад (Look Behinds)

Позволяет просмотреть строку назад и определить наличие совпадений с шаблоном.
Также разделяется на положительное и отрицательное.
Положительное — записывается «?

$string = ‘I live in the whitehouse’ ;

// try to match house preceded by white
if ( preg_match ( «/(? , $string ) ) <
// if we find the word white, not followed by house
echo ‘Совпадение’ ;
> else <
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
Совпадение

Здесь мы нашли совпадение, потому что паттерн «house» сразу следует за паттерном «house».
Движок регулярных выражений «посмотрел назад» шаблона «house» и определил совпадение.

Если мы хотим, чтобы «house» НЕ следовал за словом «white»?
Используем отрицительное заглядывание назад — «?

/*** a simple string ***/
$string = ‘I live in the whitehouse’ ;

/*** try to match house preceded by white ***/
if ( preg_match ( «/(? , $string ) )
<
/*** if we find the word white, not followed by house ***/
echo ‘Совпадение’ ;
>
else
<
/*** if no match is found ***/
echo ‘Не думаю’ ;
>
?>

Результат скрипта:
no match is found

Потому что отрицательное заглядывание не нашло шаблона «house» c шаблоном «white» в начале его.
Давайте поменяем цвет «дома», белым слишком девственный для правительственного здания.

$string = ‘I live in the bluehouse’ ;

// ищем `house` с непредшествующим `white`
if ( preg_match ( «/(? , $string ) ) <
/*** if we find the word white, not followed by house ***/
echo ‘Совпадение’ ;
> else <
/*** if no match is found ***/
echo ‘Не думаю’ ;
>
?>

Мы изменили «whitehouse» на «bluehouse» и теперь наша регулярка сработала, потому что
шаблон «white» не обнаружен перед «house».

По-умолчанию регулярки жадные, это значит что квантификаторы (какое слово страшное)
*, +, ? «пожирают» столько символов сколько могут.

/*** 4 x and 4 z chars ***/
$string = «xxxxzzzz» ;

/*** greedy regex ***/
preg_match ( «/^(.*)(z+)$/» , $string , $matches ) ;

/*** results ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Первый паттерн (.*) совпал со всеми четыремя «x» и тремя из четырех символов «z».
Сработала жадность — шаблон забрал столько символов, сколько было в искомой строке.
Проще простого помочь перестать квантификаторам быть жадными, добавив «?» к квантификатору как в примере:

/*** string of characters ***/
$string = «xxxxzzzz» ;

/*** a non greedy match ***/
preg_match ( «/^(.*?)(z+)$/» , $string , $matches ) ;

/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Теперь $matches[1] содержит четыре «x» символа и $matches[2] четыре символа «z».
Потому что квантификатор «?» изменил поведение шаблона с «взять как можно БОЛЬШЕ» на «взять как можно МЕНЬШЕ».

Чтобы сделать нежадным весь шаблон, используем модификатор «U».

/*** string of characters ***/
$string = «xxxxzzzz» ;

/*** a non greedy match ***/
preg_match ( «/^(.*)(z+)$/U» , $string , $matches ) ;

/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Результат как в предыдущем примере.

Подводные камни c ? и U

Важно заметить, что модификатор «U» не только делает поиск нежадным, он инвертирует поведение жадности квантификатора «?».
Если использовался квантификатор «?» и одновременно модификатор «U», действие «?» будет инвертировано.

/*** string of characters ***/
$string = «xxxxzzzz» ;

/*** a non greedy match ***/
preg_match ( «/^(.*?)(z+)$/U» , $string , $matches ) ;

/*** show the matches ***/
echo $matches [ 1 ] ;
echo «
» ;
echo $matches [ 2 ] ;
?>

Результат скрипта:
xxxxzzz
Delimiters

В этом мане было рассмотрено много регулярок и все они разделялись слэшем «/».
Иногда нам нужно находить в шаблоне слэш и когда он одновременно является разделителем регуляного выражения,
нам придется экранировать каждый встречающийся слэш, что неудобно.

Поэтому в качестве разделителя можно взять любой символ, например #, @, ^ и т.п.

/*** get the host name from a url ***/
preg_match ( ‘#^(?:http://)?([^/]+)#i’ , «http://www.phpro.org/tutorials» , $matches ) ;

/*** show the host name ***/
echo $matches [ 1 ] ;
?>

Примеры

// the string to match against
$string = ‘The cat sat on the mat’ ;

// match the beginning of the string
echo preg_match ( «/^The/» , $string ) ;

// match the end of the string
// returns 1
echo preg_match ( «/mat \z /» , $string ) ;

// match anywhere in the string
// returns 0 as no match was found for dog.
echo preg_match ( «/dog/» , $string ) ;
?>

Поиск нескольких шаблонов

// the string to match against
$string = ‘The cat sat on the matthew’ ;

// matches the letter «a» followed by zero or more «t» characters
echo preg_match ( «/at*/» , $string ) ;

// matches the letter «a» followed by a «t» character that may or may not be present
echo preg_match ( «/at?/» , $string ) ;

// matches the letter «a» followed by one or more «t» characters
echo preg_match ( «/at+/» , $string ) ;

// matches a possible letter «e» followed by one of more «w» characters anchored to the end of the string
echo preg_match ( «/e?w+ \z /» , $string ) ;

// matches the letter «a» followed by exactly two «t» characters
echo preg_match ( «/at<2>/» , $string ) ;

// matches a possible letter «e» followed by exactly two «t» characters
echo preg_match ( «/e?t<2>/» , $string ) ;

// matches a possible letter «a» followed by exactly 2 to 6 «t» chars (att attt atttttt)
echo preg_match ( «/at<2,6>/» , $string ) ;

Запомните, preg_match() возвращает только 0 или 1, и останавливается после первого успешного нахождения шаблона.

Чтобы найти все совпадения — используйте preg_match_all().

Чит Шит

\w — Any “word” character (a-z 0-9 _)
\W — Any non “word” character
\s — Whitespace (space, tab CRLF)
\S — Any non whitepsace character
\d — Digits (0-9)
\D — Any non digit character
. — (Period) – Any character except newline

^ — Start of subject (or line in multiline mode)
$ — End of subject (or line in multiline mode)
[ — Start character class definition
] — End character class definition
| — Alternates, eg (a|b) matches a or b
( — Start subpattern
) — End subpattern
\ — Escape character

n- Zero or more of n
n+ — One or more of n
n? — Zero or one occurrences of n
— n occurrences exactly
— At least n occurrences
— Between n and m occurrences (inclusive)

i — Case Insensitive
m — Multiline mode — ^ and $ match start and end of lines
s — Dotall — . class includes newline
x — Extended– comments and whitespace
e — preg_replace only – enables evaluation of replacement as PHP code
S — Extra analysis of pattern
U — Pattern is ungreedy
u — Pattern is treated as UTF-8

\b — Word boundary
\B — Not a word boundary
\A — Start of subject
\Z — End of subject or newline at end
\z — End of subject
\G — First matching position in subject

(?=) — Positive look ahead assertion foo(?=bar) matches foo when followed by bar
(?!) — Negative look ahead assertion foo(?!bar) matches foo when not followed by bar
(? ) — Once-only subpatterns (?>\d+)bar Performance enhancing when bar not present
(?(x)) — Conditional subpatterns
(?(3)foo|fu)bar — Matches foo if 3rd subpattern has matched, fu if not
(?#) — Comment (?# Pattern does x y or z)

Дополнения от меня

Posix символьные классы

Дополнительные шорткуты для шаблонов. Могут применяться только внутри классов.
Пример для поиска числа с пробелами — preg_match(«@[[:space:]\d]+@», $string)

Внутренние модификаторы шаблонов

Модификаторы m, s, x, U, X, J могут использоваться внутри шаблона.
Например (?im) установит мультистроковой регистронезивисимый метод поиска для паттерна.
Отключить внутренние модификаторы можно перечислив их через дефис, например (?im-sx)

Пример:
шаблон (?i:foo) совпадет с «FoO»

Именованный «захват»

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

Записывается: (? ), (?’name’) или (?P ).
Раньше поддерживался только такой синтаксис: (?P ). [

preg_match ( ‘/Name: (.+), Age: ( \d +)/’ , $text , $matches ) ;
preg_match ( ‘/Name: (?P .+), Age: (?P \d +)/’ , $text , $matches ) ;
?>

Результат скрипта:
array(‘Name’ => ‘строка’, ‘Age’ => ‘число’)

Замена через callback-функцию

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

\s * \w |’ ,
create_function (
‘$matches’ ,
‘return strtoupper($matches[0]);’
) ,
$line
) ;
?>

Данный код заменит все первые буквы в параграфах на заглавные.

В php >= 5.3 callback-функцию можно записать в сокращенном виде

\s * \w |’ ,
function ( $matches ) <
return strtoupper ( $matches [ 0 ] ) ;
> ,
$line
) ;
?>

Илон Маск рекомендует:  Правила дизайна сайта
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL