Php как составить регулярное выражение

Время на прочтение
9 мин

Количество просмотров 99K

В преддверии старта нового потока по курсу «Backend-разработчик на PHP», а также смежного с ним курса «Framework Laravel», хотим поделиться статьей, которую подготовил наш внештатный автор.

Внимание! данная статья не имеет отношения к программе курса и будет полезна только для новичков. Для получения более углубленных знаний приглашаем вас посетить бесплатный двухдневный онлайн интенсив по теме: «Создание Telegram-бота для заказа кофе в заведении и оплаты онлайн». Второй день интенсива будет проходить тут.



Всем привет! Всех с наступившим [20]{2,}0 годом. Сегодня я хочу затронуть тему, которая иногда является темой для шуток от «Да зачем тебе все это учить, если есть уже есть готовые решения» до «может тебе еще и весь Perl выучить?». Однако время идет, множество программистов начинают осваивать регулярные выражения, а на Хабре нет ни одной свежей (хоть регулярные выражения не слишком изменились за последнее время) статьи на этой тематику. Пришло время написать ещё одну!

Регулярные выражения в отрыве от их конкретной реализации

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

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

Если они вроде простые, тогда почему такие страшные на первый взгляд?

На самом деле любое выражение может быть «регулярным» и применяться для проверки или поиска каких-либо символов. Например, слова Pavel или example@mail.ru тоже могут использоваться как регулярки, только, понятное дело, в довольно узком ключе. Для проверки работы регулярных выражений в среде PHP без запуска своего сервера или хостинга вы можете воспользоваться следующим онлайн сервисом (вот только на нем у меня не работала обработка русских символов). Для начала в качестве регулярного выражения мы используем просто Pavel.

Положим у нас есть следующий текст:

Pavel knows too much. Pavel using nginx and he’s not rambler.

Сейчас регулярные выражения нашли оба вхождения слова Pavel. Здорово, но звучит не очень полезно (разве что только вы зачем-то пытаетесь проанализировать что-то вроде количества упоминания слова сударь в Войне и Мире через Vim и Python, но тогда у меня к вам вопросов нет).

Вариативность выражения

Если ваше регулярное выражение вариативно (например, вам известна только некоторая его часть и нужно найти количество вхождений годов, начиная от 2000 и заканчивая 2099), то мы можем использовать следующее регулярное выражение: 20..

Текст: Молодые писатели пишут много чего. Например писатель 2002 года рождения очень отличается от 2008 и 2012

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

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

Регулярное выражение: .doc

Текст: kursach.doc , nepodozritelneyfail.exe, work.doc, shaprgalka.rtf doc

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

Совпадение с целым набором символов

В регулярных выражениях совпадения с набором обеспечивается с помощью метасимволов — квадратных скобочек [ ]. Любые два символа ASII могут быть указаны в качестве начала и конца диапазона. Для простой реализации, положим, мы хотим найти все пронумерованные файлы от 0 до 9 с расширением .jpg.

Регулярное выражение: [0-9].jpg

Текст: 1.jpg, 2.jpg, 3.jpg, photo.jpg, anime.jpg, 8.jpg, jkl.jpg

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

Регулярное выражение: [^0-9].jpg

Текст: 1.jpg, 2.jpg, 3.jpg, photo.jpg , anime.jpg , 8.jpg, jkl.jpg

Но без множественного выбора это конечно неполноценные выражения.

Полезные таблицы

Приведем таблицу метасимволов:

Таблица пробельных метасимволов

Множественный выбор: делаем простую валидацию

Вооружившись полученными знаниями, попробуем сделать регулярное выражение, которое находит, например, слова короче 3 букв (стандартная задача для антиспама). Если мы попробуем использовать следующее регулярное выражение — w{1,3} (в котором метасимвол w указывает на любой символ, а фигурные скобки обозначают количество символов от сколько до скольки, то у нас выделятся все символы подряд — нужно как-то обозначить начало и конец слов в тексте. Для этого нам потребуется метасимвол b.

Регулярное выражение: bw{1,3}b:

Текст: good word
not
egg

Неплохо! Теперь слова короче трех букв не смогут попадать в нашу базу данных. Посмотрим на валидацию почтового адреса:

Регулярное выражение: w+@w+.w+

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

Подробнее рассмотрим повторение символов

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

Регулярное выражение: [2-6]+

Текст: Here are come’s 89 different 234 digits 24 .

Давайте я приведу таблицу всех квантификаторов метасимволов:

В применении квантификаторов нет ничего сложного. Кроме одного нюанса: жадные и ленивые квантификаторы. Приведем таблицу:

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

Регулярное выражение: <h[1-7]>.*?</h[1-7]>

Текст: <h7> hello </h7> lorem ipsum avada kedavra <h7> buy</h7>

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

Границы символьных строк

Границы символьных строк мы уже использовали выше. Приведем здесь более подробную таблицу:

Работа с подвыражениями

Подвыражения в регулярных выражениях делаются с помощью метасимвола группировки ().
Приведем пример регулярного выражения, которое универсально может находить различные вариации IP — адресов.

Регулярное выражение: (((25[0-5])|(2[0-4]d)|(1d{2})|(d{1,2})).){3}(((25[0-5]|(2[0-4]d)|(1d{2})|(d{1,2}))))

Текст: 255.255.255.255 просто адрес
191.198.174.192 wikipedia
87.240.190.67 vk
31.13.72.36 facebook

Здесь используется логический оператор | (или), который позволяет нам составить регулярное выражение, которое соответствует правилу, по которому составляются IP- адреса. В IP адресе должно быть от 1 и до 3 цифр, в котором число из трех чисел может начинаться с 1, с 2 (или тогда вторая цифра должна быть в пределах от 0 и до 4), или начинаться с 25, и тогда 3 цифра оказывается в пределах от 0 и до 5. Также между каждой комбинацией цифр должна стоять точка. Используя приведенные выше таблицы, постарайтесь сами расшифровать регулярное выражение сверху. Регулярные выражения в начале пугают своей длинной, но длинные не значит сложные.

Просмотр вперед

Для просмотра выражения на любую комбинацию определенных символов указывается шаблон по которому обнаруживается, но не возвращается, совпадение. По существу, просмотр вперед определяет подвыражение и поэтому он формируется соответствующим образом. Синтаксический шаблон для просмотра вперед состоит из подвыражения, перед которым стоит ?=, а после равно следует сопоставляемый текст.

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

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

Регулярное выражение: /^(?=.*[a-z])(?=.*[A-Z])(?=.*d)[a-zA-Zd]{8,}$/

Текст: Qwerty123
Im789098
weakpassword

Особенности работы регулярных выражений именно в PHP

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

Разделителем могут выступать произвольные символы, кроме буквенно-цифровых, обратного слеша » и нулевого байта. Если символ разделителя встречается в шаблоне, его необходимо экранировать . В качестве разделителей доступны комбинации, пришедшие из Perl: (), {}, [].

Какие функции используются в php? В пакете PCRE предоставляются следующие функции для поддержки регулярных выражений:

  • preg_grep() — выполняет поиск и возвращает массив совпадений.
  • preg_match() — выполняет поиск первого совпадения с помощью регулярных выражений
  • preg_match_all() — выполняет глобальный поиск с помощью регулярных выражений
  • preg_quote() — принимает шаблон и возвращает его экранированную версию
  • preg_replace() — выполняет операцию поиска и замены
  • preg_replace_callback() — тоже выполняет операцию поиска и замены, но используют callback – функцию для любой конкретной замены
  • preg_split() — разбивает символьную строку на подстроки

Для организации совпадения без учета регистра букв служит модификатор i.
С помощью модификатора m можно активировать режим обработки многострочного текста.

Замещающие строки допускается вычислять в виде кода PHP. Для активизации данного режима служит модификатор e.

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

Обратные ссылки могут обозначаться с помощью знака $ (например $1), а в более ранних версиях вместо знака $ применяются знаки \.
Метасимволы E, l, L, u и U не используются (поэтому они и не были упомянуты в этой статье).

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

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

	$pattern_name = '/w{3,}/';
	$pattern_mail = '/w+@w+.w+/';
	$pattern_password = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*d)[a-zA-Zd]{8,}$/';
	
	if (preg_match($pattern_name, $name) &&
		preg_match($pattern_mail, $mail) &&
		preg_match($pattern_password, $_POST['password'])) {
 # тут происходит, к примеру, регистрация нового пользователя, отправка ему письма, и внесение в базу данных 
		}

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

По традиции, несколько полезных ссылок:

Шпаргалка от MIT по регулярным выражениям
Официальная часть документации php по регулярным выражениям.

На этом все. До встречи на интенсиве!
Второй день интенсива пройдет тут

What is a Regular Expression?

The regular expression is basically started from mathematics which defines a range of characters for some purpose. Different languages get references from this mathematical concept and applied it for searching patterns and validation of data. In this article, you will learn regex in PHP.

There are many use cases of regex in PHP like searching, validating, etc. In this article, you will learn about regular expressions in search patterns. Once you will be able to understand the regex, you can use it anywhere in PHP.

A regular expression can be used to search text from strings or to replace specific characters or strings.

A regular expression can be a single character or combination of some complex patterns.

Syntax of regular expression in PHP

The delimiter can be any character that is not a letter, number, backslash, or space. The most common delimiter is the forward-slash (/), but when your pattern contains forward slashes it is convenient to choose other delimiters such as # or ~.

Generally, regular expression in PHP consists of three parts.

  1. Delimiter – It specifies that tells the beginning or end of the string in the pattern. A delimiter cannot be a backslash, number, letter, or space. However, a forward slash can be used as a delimiter. If the patterns you are searching for consist of forwarding slashes, you can change the delimiter to tilt ~ or hash #.
  2. Pattern – It specified the pattern or sequence of characters to search.
  3. Modifiers (optional) – You can make the matching of pattern cases insensitive or sensitive.

Example

$exp = "/php.org/i";

RegextFunctions in PHP

PHP provides built-in functions for regular expressions. The most common regex functions in PHP are:

  • Preg_replace() – It counts the number of times the pattern occurs in the string and return the count.
  • Preg_match() – returns 0 in case of pattern not found in the string. 1 in case of found.
  • Preg_match_all() – This function replaces the string with another string where the pattern is matched. You will get a more clear idea in the next section if you are finding it hard to understand.

preg_match function in PHP

Preg_match function returns the binary result. That is either 0 or 1. If the string contains the pattern you specify in the first argument of the preg_match function, it will return 1. 0 in case of not found.

Look at the following example, in which we search the string for characters PHP.

<?php
$str = "Visit php.org";
$pattern = "/php/i";
echo preg_match($pattern, $str); // Outputs 1
?>

preg_match_all function in PHP

This function does not tell if the pattern exists in the string or not. It returns the count of the number of times a pattern appears in the string. Look at the following example in which we have performed a case-insensitive search of patterns ing in the given string.

Example

<?php
$str = "It is raining heavily. Cars are slipping outside. ";
$pattern = "/ing/i";
echo preg_match_all($pattern, $str); // Outputs 4
?>

/i in the above example specify that the string can be either in lower case or upper case.

preg_replace function in PHP

preg_replace function returns a new string by replacing the pattern found in the string with some other string of characters. This function accepts three parameters. The first parameter is the pattern to search in the string in the second parameter. Finally, the third parameter is the string to put in place of the pattern found in the string.

Look at the following example, in which we replace the word website with PHP.org

Example

<?php
$str = "Visit Website!";
$pattern = "/Website/i";
echo preg_replace($pattern, "php.org", $str); // Outputs "Visit php.org!"
?>

Regular Expression Modifiers

You can adjust the search behavior of the regex in PHP by defining the following modifier variables.

  1. I – Used to perform case-insensitive searching.
  2. U – For the correct searching of utf-8 patterns.
  3. M – Adds multi-searching in the PHP regex. There are some patterns that search at the beginning or end of each line. So, these patterns look at the beginning and end of each line of the string.

Specify range in PHP regex

Understand the following three concepts. It will help you out to put the range in patterns while searching text or replacing it.

  1. [abc] – The square brackets indicated that find any one character from these characters in the string.
  2. [^0-9] – Look for the characters not in the range within the brackets.
  3. [0-9] – Find any one character in between 0 to 9. 0 and 9 are inclusive in this case.

You can learn more about Regex functions in PHP here

Регулярные выражения позволяют найти в строке последовательности, соответствующие шаблону.
Например шаблон «Вася(.*)Пупкин» позволит найти последовательность когда между словами Вася и Пупкин будет любое количество любых символов.
Если надо найти шесть цифр, то пишем «[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 (прописью: сто двадцать пять миллиардов операций).
Конечно же, если подходить строго, там стольких операций не будет, а будет раза в четыре-восемь меньше,
но важен сам порядок цифр.

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

. точка любой символ
[<символы>] квадратные скобки класс символов («любое из»). Например [abcdef]
[^<символы>]   негативный класс символов («любое кроме»)
тире обозначение последовательности в классе символов («[0-9]» — цифры)
d [0-9] Только цифры
D [^0-9] Кроме цифр
w [a-z0-9] Буквы и цифры
W [^a-z0-9] Кроме букв и цифр
s [ ] Пробельные символы: пробел, табуляция, перевод строки
S [^ ] Кроме пробельных символов
| (одно|другое) На этом месте может быть один из перечисленных вариантов,
например: (Вася|Петя|Маша). Если Вы не хотите, чтобы это попало в выборку используйте (?: … )

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

Квантификатор

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

{<количество>}

либо

{<минимум>, <максимум>}

Если нужно указать только необходимый минимум, а максимума нет, просто ставим запятую и не пишем второе число:
«{5,}» («минимум 5»). Для наиболее часто употребляемых квантификаторов есть специальные обозначения:

* «звёздочка» или знак умножения {0,}
+ плюс {1,}
? вопросительный знак {0,1}

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

Якоря

^ привязка к началу строки
$ привязка к концу строки

Эти символы должны стоять соответственно в самом начале и в самом конце строки.

Жадность

Вопросительный знак выступает еще и как минимизатор квантификатора:
.*?

$str = '[b]жирный текст [b]а тут - еще жирнее[/b] вернулись[/b]';
$to  = '<b>$1</b>';
$re1 = '|[b] (.*)  [/b]|ixs';
$re2 = '|[b] (.*?) [/b]|ixs';
$result = preg_replace($re1, $to, $str);
echo "Жадная версия: ".htmlspecialchars($result)."<br>";
$result = preg_replace($re2, $to, $str);
echo "Ленивая версия: ".htmlspecialchars($result)."<br>";

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

Жадная версия: <b>жирный текст [b]а тут - еще жирнее[/b] вернулись</b>
Ленивая версия: <b>жирный текст [b]а тут - еще жирнее</b> вернулись[/b]

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

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

многостроковый режим. По умолчанию PCRE ищет совпадения с шаблоном
только внутри одной строки, а символы «^» и «$» совпадают только с началом и концом всего текста.
Когда этот параметр установлен, «^» и «$» совпадают с началом и концом отдельных строк.

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

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

  • preg_grep — Возвращает массив вхождений, которые соответствуют шаблону
  • preg_match — Выполняет проверку на соответствие регулярному выражению. Данная функция ищет только первое совпадение!
  • preg_match_all — Выполняет глобальный поиск шаблона в строке
  • preg_quote — Экранирует символы в регулярных выражениях.
    Т.е. вставляет слэши перед всеми служебными символами (например, скобками, квадратными скобками и т.п.),
    чтобы те воспринимались буквально. Если у вас есть какой-либо ввод информации пользователем,
    и вы проверяете его с помощью регулярных выражений, то лучше перед этим заэкранировать служебные символы в пришедшей переменной
  • preg_replace — Выполняет поиск и замену по регулярному выражению
  • preg_replace_callback — Выполняет поиск по регулярному выражению и замену
  • preg_split — Разбивает строку по регулярному выражению

preg_grep

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

Синтаксис

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

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

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

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

// Возвращает все элементы массива,
// содержащие числа с плавающей точкой
$fl_array = preg_grep("/^(d+)?.d+$/", $array);

preg_match

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

Синтаксис

int preg_match ( string pattern, string subject [, array matches [, int flags [, int offset]]])
Ищет в заданном тексте subject совпадения с шаблоном pattern

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

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

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

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

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

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

Пример кода

// Символ "i" после закрывающего ограничителя шаблона означает
// регистронезависимый поиск.
if (preg_match("/php/i", "PHP is the web scripting language of choice.")) {
    echo "Вхождение найдено.";
} else {
    echo "Вхождение не найдено.";
}

Пример кода

/*
    Специальная последовательность b в шаблоне означает границу слова,
    следовательно, только изолированное вхождение слова 'web' будет соответствовать
    маске, в отличие от "webbing" или "cobweb".
*/
if (preg_match("/bwebb/i", "PHP is the web scripting language of choice.")) {
    echo "Вхождение найдено.";
} else {
    echo "Вхождение не найдено.";
}

if (preg_match("/bwebb/i", "PHP is the website scripting language of choice.")) {
    echo "Вхождение найдено.";
} else {
    echo "Вхождение не найдено.";
}

Пример кода

// Извлекаем имя хоста из URL
preg_match("/^(http://)?([^/]+)/i",
    "http://www.htmlweb.ru/index.html", $matches);
$host = $matches[2];

// извлекаем две последние части имени хоста
preg_match("/[^./]+.[^./]+$/", $host, $matches);
echo "domain name is: {$matches[0]}n";

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

domain name is: htmlweb.ru

preg_match_all

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

Синтаксис

int preg_match_all (string pattern, string subject, array matches [, int flags [, int offset]])

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

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

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

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

Пример кода

preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_PATTERN_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "n";
echo $out[1][0] . ", " . $out[1][1] . "n";

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

<b>example: </b>, <div align="left">this is a test</div>
example: , this is a test

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

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

Пример кода

preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align="left">this is a test</div>",
    $out, PREG_SET_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "n";
echo $out[1][0] . ", " . $out[1][1] . "n";

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

<b>example: </b>, example:
<div align="left">this is a test</div>, this is a test

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

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

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

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

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

Пример кода

preg_match_all("/(?  (d{3})?  )?  (?(1)  [-s] ) d{3}-d{4}/x",
                "Call 555-1212 or 1-800-555-1212", $phones);

Пример кода

// Запись \2 является примером использования ссылок на подмаски.
// Она означает необходимость соответствия подстроки строке, зафиксированной
// второй подмаской, в нашем примере это ([w]+).
// Дополнительный слеш необходим, так как используются двойные кавычки.

$html = "<b>bold text</b><a href=howdy.html>click me</a>";

preg_match_all("/(<([w]+)[^>]*>)(.*)(</\2>)/", $html, $matches);

for ($i=0; $i< count($matches[0]); $i++) {
  echo "matched: " . $matches[0][$i] . "n";
  echo "part 1: " . $matches[1][$i] . "n";
  echo "part 2: " . $matches[3][$i] . "n";
  echo "part 3: " . $matches[4][$i] . "nn";
}

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

matched: <b>bold text</b>
part 1: <b>
part 2: bold text
part 3: </b>

matched: <a href=howdy.html>click me</a>
part 1: <a href=howdy.html>
part 2: click me
part 3: </a>

preg_quote

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

Синтаксис

string preg_quote (string str [, string delimiter])

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

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

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

Пример кода

$keywords = "$40 for a g3/400";
$keywords = preg_quote($keywords, "/");
echo $keywords; // возвращает $40 for a g3/400

Пример кода

// Выделение курсивом слова в тексте
// В данном примере preg_quote($word) используется, чтобы
// избежать трактовки символа '*' как спец. символа.
$textbody = "This book is *very* difficult to find.";
$word = "*very*";
$textbody = preg_replace ("/" . preg_quote($word) . "/",
                          "<i>" . $word . "</i>",
                          $textbody);
echo $textbody;

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

This book is <i>*very*</i> difficult to find.

preg_replace

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

Синтаксис

mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])

Выполняет поиск в строке 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.

Пример кода

$string = "April 15, 2003";
$pattern = "/(w+) (d+), (d+)/i";
$replacement = "${1}1,$3";
echo preg_replace($pattern, $replacement, $string);

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

April1,2003.

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

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

// Использование массивов с числовыми индексами в качестве аргументов
// функции preg_replace()
$string = "The quick brown fox jumped over the lazy dog.";

$patterns[0] = "/quick/";
$patterns[1] = "/brown/";
$patterns[2] = "/fox/";

$replacements[2] = "bear";
$replacements[1] = "black";
$replacements[0] = "slow";

echo preg_replace($patterns, $replacements, $string);

The bear black slow jumped over the lazy dog.

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

ksort($patterns);
ksort($replacements);
echo preg_replace($patterns, $replacements, $string);

The slow black bear jumped over the lazy dog.

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

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

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

Пример кода: Замена по нескольким шаблонам

// Замена по нескольким шаблонам
$patterns = array ("/(19|20)(d{2})-(d{1,2})-(d{1,2})/",
                   "/^s*{(w+)}s*=/");
$replace = array ("\3/\4/\1\2", "$\1 =");
echo preg_replace($patterns, $replace, "{startDate} = "1999-5-27";");

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

$startDate = «5/27/1999»;

Пример кода: Использование модификатора /e

// Использование модификатора /e
preg_replace("/(</?)(w+)([^>]*>)/e",
              "'\1'.strtoupper('\2').'\3'",
              $html_body);

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

// Конвертор HTML в текст
// $document на выходе должен содержать HTML-документ.
// Необходимо удалить все HTML-теги, секции javascript,
// пробельные символы. Также необходимо заменить некоторые
// HTML-сущности на их эквивалент.

$search = array ("'<script[^>]*?>.*?</script>'si",  // Вырезает javaScript
                 "'<[/!]*?[^<>]*?>'si",           // Вырезает HTML-теги
                 "'([rn])[s]+'",                 // Вырезает пробельные символы
                 "'&(quot|#34);'i",                 // Заменяет HTML-сущности
                 "'&(amp|#38);'i",
                 "'&(lt|#60);'i",
                 "'&(gt|#62);'i",
                 "'&(nbsp|#160);'i",
                 "'&(iexcl|#161);'i",
                 "'&(cent|#162);'i",
                 "'&(pound|#163);'i",
                 "'&(copy|#169);'i",
                 "'&#(d+);'e");                    // интерпретировать как php-код

$replace = array ("",
                  "",
                  "\1",
                  """,
                  "&",
                  "<",
                  ">",
                  " ",
                  chr(161),
                  chr(162),
                  chr(163),
                  chr(169),
                  "chr(\1)");

$text = preg_replace($search, $replace, $document);

preg_replace_callback

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

Синтаксис

mixed preg_replace_callback (mixed pattern, callback callback, mixed subject [, int limit])

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

Пример кода

/* фильтр, подобный тому, что используется в системах Unix
 для преобразования в заглавные начальных букв параграфа */

$fp = fopen("php://stdin", "r") or die("can't read stdin");
while (!feof($fp)) {
    $line = fgets($fp);
    $line = preg_replace_callback(
        '|<p>s*w|',
        create_function(
            // Использование одиночных кавычек в данном случае принципиально,
            // альтернатива - экранировать все символы '$'
            '$matches',
            'return strtolower($matches[0]);'
            ),
            $line
        );
    echo $line;
}
fclose($fp);

preg_split

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

Синтаксис

array preg_split (string pattern, string subject [, int limit [, int flags]])

Возвращает массив, состоящий из подстрок заданной строки 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
В случае, если этот флаг указан, для каждой найденной подстроки, будет указана ее позиция в исходной строке.
Необходимо помнить, что этот флаг меняет формат возвращаемых данных:
каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение.

Примеры кода

// Получение подстрок из заданного текста
// разбиваем строку по произвольному числу запятых и пробельных символов,
// которые включают в себя  " ", r, t, n и f
$keywords = preg_split("/[s,]+/", "hypertext language, programming");
// Разбиваем строку на составляющие символы
$str = 'string';
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
$str = 'hypertext language programming';
$chars = preg_split('/ /', $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
print_r($chars);

В случае, если после открывающей круглой скобки следует «?:«, захват строки не происходит,
и текущая подмаска не нумеруется. Например, если строка «the white queen»
сопоставляется с шаблоном the ((?:red|white) (king|queen)), будут захвачены подстроки «white queen» и «queen»,
и они будут пронумерованы 1 и 2 соответственно:

$r="/the ((?:red|white) (king|queen))/";
0="the white king";
1="white king";
2="king";

Еще про регулярные выражения:

  • примеры регулярных выражений
  • все функции PHP для работы с регулярными выражениями
  • Регулярные выражения в Javascript

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

  • www.pagecolumn.com
  • erik.eae.net
  • www.regexpal.com

Читать дальше: Библиотека Curl в PHP


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

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

PHP (версия 5.3+) поддерживает регулярные выражения в синтаксисе Perl. Perl (Practical Extraction and Report Language) был первым распространенным языком программирования, который обеспечивал интегрированную поддержку регулярных выражений и большие возможности обработки и манипулирования текстом.

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

Функция Что делает
preg_match() Выполняет сопоставление регулярного выражения.
preg_match_all() Выполняет глобальное сопоставление регулярного выражения.
preg_replace() Выполняет поиск и замену по регулярному выражению.
preg_grep() Возвращает элементы входного массива, соответствующие шаблону.
preg_split() Разбивает строку на подстроки с помощью регулярного выражения.
preg_quote() Цитирует символы регулярного выражения, найденные в строке.

PHP-функция preg_match() прекращает поиск после нахождения первого совпадения, тогда как функция preg_match_all() продолжает поиск до конца строки и находит все возможные совпадения вместо остановки на первом совпадении.

Синтаксис регулярных выражений

Синтаксис регулярных выражений включает использование специальных символов (не путать со специальными символами HTML). В регулярном выражении особое значение имеют следующие символы: . * ? + [ ] ( ) { } ^ $ | . Вам нужно будет использовать обратную косую черту (слеш) для этих символов всякий раз, когда вы захотите использовать их буквально. Например, если вы хотите использовать в регулярном выражении символ . вам нужно будет писать .. Все остальные символы автоматически принимают свои буквальные значения.

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

Классы символов

Квадратные скобки, окружающие набор символов, называются классом символов, например [abc]. Класс символов всегда соответствует одному символу из списка указанных символов, что означает, что выражение [abc] соответствует только символу a, b или c.

Также могут быть определены классы отрицательных символов, соответствующие любому символу, кроме символов, содержащихся в скобках. Класс инвертируемых символов определяется помещением символа каретки (^) сразу после открывающей скобки, как, например [^abc].

Вы также можете определить диапазон символов, используя символ дефиса (-) внутри класса символов, например [0-9]. Давайте посмотрим на несколько примеров этих классов:

RegExp Что делает
[abc] Соответствует любому из символов a, b или c.
[^abc] Соответствует любому символу, кроме a, b или c.
[a-z] Соответствует любому символу от строчного a до строчного z.
[A-Z] Соответствует любому символу от верхнего регистра A до верхнего регистра Z.
[a-Z] Соответствует любому символу от нижнего a до верхнего Z.
[0-9] Соответствует одной цифре от 0 до 9.
[a-z0-9] Соответствует одиночному символу между a и z или между 0 и 9.

В следующем примере показано, как определить, существует ли шаблон в строке или нет, используя регулярное выражение и PHP-функцию preg_match():

<?php
$pattern = "/ca[kf]e/";
$text = "He was eating cake in the cafe.";
if(preg_match($pattern, $text)){
    echo "Match found!";
} else{
    echo "Match not found.";
}
?>

Точно так же вы можете использовать функцию preg_match_all(), чтобы найти все совпадения в строке:

<?php
$pattern = "/ca[kf]e/";
$text = "He was eating cake in the cafe.";
$matches = preg_match_all($pattern, $text, $array);
echo $matches . " matches were found.";
?>

Регулярные выражения не являются уникальными для PHP. Такие языки, как Java, Perl, Python и т. д., используют ту же нотацию для поиска шаблонов в тексте.

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

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

Shortcut Что делает
. Соответствует любому одиночному символу, кроме новой строки n.
d Соответствует любому цифровому символу. Тоже, что и [0-9]
D Соответствует любому нецифровому символу. Тоже, что и [^0-9]
s Соответствует любому пробельному символу (пробел, табуляция, новая строка или символ возврата каретки). Тоже, что и [ tnr]
S Соответствует любому непробельному символу. Тоже, что и [^ tnr]
w Соответствует любому буквенному символу (определяется как от a до z, от A до Z, от 0 до 9 и подчеркивание). Тоже, что и [a-zA-Z_0-9]
W Соответствует любому не буквенному символу. Тоже, что и [^a-zA-Z_0-9]

В следующем примере показано, как найти и заменить пробел символом дефиса в строке с помощью регулярного выражения и PHP-функции preg_replace():

<?php
$pattern = "/s/";
$replacement = "-";
$text = "Earth revolves aroundnthetSun";
// Заменяем пробелы, символы новой строки и табуляции
echo preg_replace($pattern, $replacement, $text);
echo "<br>";
// Заменяем только пробелы
echo str_replace(" ", "-", $text);
?>

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

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

В следующей таблице перечислены различные способы количественной оценки конкретного паттерна:

RegExp Что делает
p+ Соответствует одному или нескольким вхождениям буквы p.
p* Соответствует нулю или более вхождений буквы p.
p? Соответствует нулю или одному появлению буквы p.
p{2} Соответствует ровно двум вхождениям буквы p.
p{2,3} Соответствует как минимум двум, но не более трем появленям буквы p.
p{2,} Соответствует двум или более вхождениям буквы p.
p{,3} Соответствует не более чем трем появлениям буквы p

Регулярное выражение в следующем примере разбивает строку на запятую, последовательность запятых, пробелы или их комбинацию с помощью PHP-функции preg_split():

<?php
$pattern = "/[s,]+/";
$text = "My favourite colors are red, green and blue";
$parts = preg_split($pattern, $text);
 
// Перебираем массив частей и отображать подстроки
foreach($parts as $part){
    echo $part . "<br>";
}
?>

Начало и конец строки (якоря)

Есть определенные ситуации, когда вы захотите сопоставить начало или конец слова или строки. Для этого можно использовать два якоря — это каретка (^), обозначающая начало строки, и знак доллара ($), обозначающий конец строки.

RegExp Что делает
^p Соответствует букве p в начале строки.
p$ Соответствует букве p в конце строки.

Регулярное выражение в следующем примере будет отображать только те имена из массива names, которые начинаются с буквы «J» с использованием PHP-функции preg_grep():

<?php
$pattern = "/^J/";
$names = array("Jhon Carter", "Clark Kent", "John Rambo");
$matches = preg_grep($pattern, $names);
 
// Перебираем массив и отображаем совпадающие имена
foreach($matches as $match){
    echo $match . "<br>";
}
?>

Модификаторы (флаги)

Модификатор шаблона позволяет вам контролировать способ обработки соответствия шаблону. Модификаторы размещаются непосредственно после регулярного выражения, например, если вы хотите искать шаблон без учета регистра, вы можете использовать модификатор i, например: /pattern/i.

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

Модификатор Что делает
i Делает совпадение нечувствительным к регистру.
m Изменяет поведение ^ и $ для соответствия границе новой строки (т. е. начало или конец каждой строки в многострочной строке) вместо границы строки.
g Выполняет глобальное сопоставление, т.е. ищет все вхождения.
o Оценивает выражение только один раз.
s Изменяет поведение . (точка) для соответствия всем символам, включая символы новой строки.
x Позволяет использовать пробелы и комментарии в регулярном выражении для ясности.

В следующем примере показано, как выполнить глобальный поиск без учета регистра с использованием модификатора i и PHP-функции preg_match_all().

<?php
$pattern = "/color/i";
$text = "Color red is more visible than color blue in daylight.";
$matches = preg_match_all($pattern, $text, $array);
echo $matches . " matches were found.";
?>

Точно так же в следующем примере показано, как сопоставить начало каждой строки в многострочной строке с помощью привязки ^ и модификатора m с PHP-функцией preg_match_all().

<?php
$pattern = "/^color/im";
$text = "Color red is more visible than ncolor blue in daylight.";
$matches = preg_match_all($pattern, $text, $array);
echo $matches . " matches were found.";
?>

Границы слов

Символ границы слова (b) помогает вам искать слова, которые начинаются и/или заканчиваются определенным шаблоном. Например, регулярное выражение /bcar/ соответствует словам, начинающимся с шаблона car, и будет соответствовать cart, carrot, или cartoon, но не будет совпадать с oscar.

Аналогично, регулярное выражение /carb/ соответствует словам, оканчивающимся шаблоном car, и будет соответствовать oscar или supercar, но не будет соответствовать cart. Аналогично, /bcarb/ соответствует словам, начинающимся и заканчивающимся шаблоном car и будет соответствовать только слову car.

Следующий пример выделит слова, начинающиеся с car жирным шрифтом:

<?php
$pattern = '/bcarw*/';
$replacement = '<b>$0</b>';
$text = 'Words begining with car: cart, carrot, cartoon. Words ending with car: scar, oscar, supercar.';
echo preg_replace($pattern, $replacement, $text);
?>

О регулярных выражениях в JavaScript см. Руководство по регулярным выражениям в JavaScript.

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

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


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


Синтаксис регулярных выражений

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

$exp = "/wm-school/i";

В приведенном выше примере, в качестве символа разделителя используется слэш /, wm-school — это шаблон, по которому идет поиск, а символ i, расположенный после второго разделителя — это модификатор, позволяющий вести поиск без учета регистра.

В качестве символа разделителя может быть любой символ, кроме буквы, цифры, обратной косой черты или пробела. Самый распространенный разделитель — это слэш /, но если ваш шаблон содержит слэш, удобно выбрать другие разделители, такие как # или ~.

Функции регулярных выражений

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

Функция Определение
preg_match() Эта функция ищет конкретный образец в некоторой строке. Он возвращает 1 (true), если шаблон существует, и 0 (false) в противном случае.
preg_match_all() Эта функция ищет все вхождения шаблона в строке. Она возвращает количество найденных совпадений с шаблоном в строке, или 0 — если вхождений нет. Функция удобна для поиска и замены.
ereg_replace() Эта функция ищет определенный шаблон строки и возвращает новую строку, в которой совпадающие шаблоны были заменены другой строкой.
eregi_replace() Функция ведет себя как ereg_replace() при условии, что поиск шаблона не чувствителен к регистру.
preg_replace() Эта функция ведет себя как функция ereg_replace() при условии, что регулярные выражения могут использоваться как в шаблоне так и в строках замены.
preg_split() Функция ведет себя как функция PHP split(). Он разбивает строку на регулярные выражения в качестве параметров.
preg_grep() Эта функция ищет все элементы, которые соответствуют шаблону регулярного выражения, и возвращает выходной массив.
preg_quote() Эта функция принимает строку и кавычки перед каждым символом, который соответствует регулярному выражению.
ereg() Эта функция ищет строку, заданную шаблоном, и возвращает TRUE, если она найдена, иначе возвращает FALSE.
eregi() Эта функция ведет себя как функция ereg() при условии, что поиск не чувствителен к регистру.

Примечание:

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

Функция preg_match()

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

Пример. Поиск подстроки «php» в строке без учета регистра:

<?php
$str = "PHP - это язык веб-сценариев.";
$pattern = "/php/i";
if (preg_match($pattern, $str)) {
  echo "Вхождение найдено.";
} else {
  echo "Вхождение не найдено.";
}

Результат выполнения кода:

Вхождение найдено.

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

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

Функция preg_match_all()

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

В примере регулярное выражение используется для подсчета числа вхождений «ain» в строку без учета регистра:

<?php
$str = "The rain in England falls mainly on the plains.";
$pattern = "/ain/i";
echo preg_match_all($pattern, $str);
?>

Результат выполнения кода:

3

Функция preg_replace()

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

В следующем функция выполняет поиск в строке совпадений с шаблоном pattern и заменяет их на replacement:

<?php
$string = "Выпускной вечер в 2021 г";
$pattern = "/2021/i";
$replacement = "2022";
echo preg_replace($pattern, $replacement, $string);
?>

Результат выполнения кода:

Выпускной вечер в 2022 г

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

Модификаторы указываются либо в скобках, например так: (?Ui), либо после закрывающего символа ‘/pattern/Ui’.

Модификатор Описание
i Выполняет поиск без учета регистра. Например «/a/i» ищет и a, и A.
m Выполняет многострочный поиск (шаблоны, которые ищут начало или конец строки, будут соответствовать началу или концу каждой строки)
u Обеспечивает правильное сопоставление шаблонов в кодировке UTF-8 (для поиска русского текста например).
U Инвертирует «жадность» (по умолчанию жадный, т.е. пытается захватить как можно большую строку, подходящую по условию).
s Если используется, то символ точка (.) соответствует и переводу строки. Иначе она ему не соответствует.
x Игнорировать пробелы. В этом случае пробелы нужно экранировать обратным слэшем .

При использовании модификаторов, можно использовать знак минус (-) для отключения модификатора. Например: (?m-i) — включаем многострочный поиск и отключаем регистронезависимый.

Шаблоны регулярных выражений

Квадратные скобки [b-d0-4xyz] означают, что нужно выбрать «один из этих символов», в данном случае — буквы b, c, d, x, y, z или цифра от 0 до 4. Внутри квадратных скобок () не работают другие спецсимволы например | или * — они обозначают обычный символ. Если в квадратных скобках в начале стоит символ ^ то смысл меняется на противоположный: «любой один символ, кроме указанных» например, [^b-d] значит «один любой символ, кроме b, c или d».

Квадратные скобки ([]) используются для нахождения ряда символов:

Выражение Описание
[abc] Один из символов a, b, c
[^abc] Любой символ кроме a, b, c
[0-9] Любой символ из диапазона от 0 до 9
[a-zА-Я] Любой символ из диапазонов

Примечание: в квадратных скобках можно указывать диапазоны символов, но следует помнить, что русская буква ё идет отдельно от алфавита и для создания регулярки «любая русская буква» нужно писать [а-яё].

Метасимволы

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

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

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

Метасимвол Описание пример
. Соответствует любому одиночному символу, кроме новой строки. /./ соответствует строке, состоящей из одного символа.
^ Соответствует началу строки. /^cars/ соответствует любой строке, которая начинается с cars.
$ Соответствует шаблону в конце строки. /com$/ соответствует строке, заканчивающейся на com, например gmail.com
* Соответствует 0 или более вхождений. /com*/ соответствует commute, computer, compromise и т.д.
+ Соответствующий предыдущему символу появляется как минимум один раз. Например, /z+oom/ соответствует zoom.
Используется для удаления метасимволов в регулярном выражении. /google.com/ будет рассматривать точку как буквальное значение, а не как метасимвол.
a-z Соответствует строчным буквам. cars
A-Z Соответствует буквам в верхнем регистре. CARS
0-9 Соответствует любому числу от 0 до 9. /0-5/ соответствует 0, 1, 2, 3, 4, 5
[…] Соответствует классу символов. /[pqr]/ соответствует pqr
| Разделяет перечисление альтернативных вариантов. /(cat|dog|fish)/ соответствует cat или dog или fish
d Любая цифра. /(d)/ соответствует цифре
s Найти пробельный символ (в т.ч. табуляция). /(s)/ соответствует пробелу
b Граница слова (начало или конец). /bWORD/ найти совпадение в начале слова

Повторения (квантификаторы)

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

Повторения символов или комбинаций описываются с помощью квантификаторов (метасимволов, которые задают количественные отношения). Есть два типа квантификаторов: общие (задаются с помощью фигурных скобок {}) и сокращенные (сокращения наиболее распространенных квантификаторов). Фигурные скобки x{1,7} задают число повторений предыдущего символа (в этом случае выражение ищет от 1 до 7 идущих подряд букв «x»).

Квантификатор Описанте
a+ Один и более раз a
a* Ноль и более раз a
a? Одна a или пусто
a{3} 3 раза a
a{3,5} От 3 до 5 раз a
a{3,} 3 и более раз a

Примечание: Если в выражении требуется поиск одного из метасимволов, вы можете использовать обратный слэш (). Например, для поиска одного или нескольких вопросительных знаков (?) можно использовать следующее выражение: $pattern = '/?+/';

Группировка

Группы (подмаски) в регулярных выражениях делаются с помощью метасимвола группировки ().

Например в выражении xyz+ знак плюс (+) относится только к букве z и это выражение ищет слова типа xyz, xyzz, xyzzz. Но если поставить скобки x(yz)+ то квантифиактор (+) относится уже к последовательности yz и регулярка ищет слова xyz, xyzyz, xyzyzyz.

<?php
$str = "Hello, boy Bananan!";
$pattern = "/Ba(na){2}n/";
echo preg_match($pattern, $str);
?>

Результат выполнения кода:

1

Ещё примеры:

Выражение Описание
^[a-zA-Z0-9_]{1,}$ Любое слово, хотя бы одна буква, число или _
+@[a-z0-9A-Z] Соответствует строке с символом @ в начале, за которым следует любая буква нижнего регистра, число от 0 до 9 или буква верхнего регистра.
([wx])([yz]) wy, wz, xy, или xz
[a-z]+ Один или более символов нижнего регистра

Практические упражнения по регулярным выражениям PHP.

Понравилась статья? Поделить с друзьями:
  • Как исправить синусоиду после инвертора
  • Ошибка с1044 на калине как исправить
  • Как найти exp на калькуляторе
  • Как составить словарик по теме дорога
  • Ssd ошибка ввода вывода на устройстве жесткий диск как исправить