Регулярные выражения. Часть 1. Введение. Специальные символы.

Наконец-то я добрался до этой статьи, в ней я попытаюсь с нуля рассказать про регулярные выражения в PHP. Для начала — что это такое?

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

Основы основ

Как я уже сказал, начну с самого нуля. Недаром же я пометил эту статью тегом «Начинающим».

А начинается всё со строки в PHP.

// создаем строку
$stroka = 'abcdefghijklmnopqrstuvwxyz0123456789';
 
// выводим строку
echo $stroka;

Если нам сперва нужно определить, находится ли abc внутри нашей строки, и только тогда вывести её, то попробуем сделать что-то подобное:

// та же самая строка 
$stroka = 'abcdefghijklmnopqrstuvwxyz0123456789';
 
if( preg_match("/abc/", $stroka) ) { // возвратит 1 в случае положительного результата (<code>abc</code> внутри строки)
	echo $stroka;
}

Код выше дан исключительно для примера, потому что это не самый оптимальный вариант поиска вхождения в строке, для этого лучше использовать PHP-функции strpos() или strstr().

Небольшое отступление про русские буквы

Хочу обратить ваше внимание, регулярные выражения PHP по умолчанию не поддерживают русские буквы и поэтому далеко не все примеры будут работать корректно, однако это легко исправляется модификатором /u (дальше всё объясню), который включает дополнительную функциональность: шаблон и строки станут обрабатываться как UTF-8 (доступно с версии PHP 4.1.0).

Подробно в следующем примере.

Верхний регистр букв

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

<?php
// строку оставляем пока что ту же
$stroka = 'abcdefghijklmnopqrstuvwxyz0123456789';
 
if( preg_match("/ABC/i", $stroka) ) { // возвратит 1, но если убрать i, то условие уже выполняться не будет
	echo $stroka;
}

А теперь то, о чём я упоминал выше — этот же самый пример не будет работать корректно с русскими буквами. Для того, чтобы это исправить, мы добавим также модификатор /u.

$stroka = 'абвгдеёжзиклмнопрстуфхцчшщъыьэюя';
 
if( preg_match("/АБВ/iu", $stroka) ) { // модификаторы можно перечислять в любом порядке
	echo $stroka;
}

Поиск соответствия в начале строки, символ ^

Для обозначения в шаблоне начала строки, используется символ каретки ^.

$stroka = 'абвгдеёжзиклмнопрстуфхцчшщъыьэюя';
 
if( preg_match("/^абв/u", $stroka) ) {
	echo 'Строка начинается с абв';
}

Проще простого, верно ведь?

Поиск соответствия концу строки. В чём отличие между \z и $

Вот тут уже интереснее. Начну с того, что есть два «конца строки», один — это конец строковой переменной в целом, а другой — конец строки в тексте \n, то есть дальше текст продолжается, просто с новой строки.

Так вот, если вам нужны именно последние символы в строковой переменной, всегда используйте \z.

// обратите внимание, что после буквы "р" я добавил переход на новую строку
$stroka = 'абвгдеёжзиклмнопр\nстуфхцчшщъыьэюя';
 
if( preg_match("/юя\z/u", $stroka) ) {
	echo 'Текст оканчивается на "юя"';
} else {
	echo 'Соответствий не найдено.';
}

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

Вообще мы можем в предыдущем примере заменить \z на $ и он будет проверять соответствие последних символов в переменной, но если включить поддержку многострочного поиска модификатором /m, то символы \n в самой строке уже будут восприниматься как переход на новую строку в тексте (для непонятливых — нажатие клавиши Enter) и тогда условие станет верным для букв пр .

$stroka = 'абвгдеёжзиклмнопр\nстуфхцчшщъыьэюя';
 
if( preg_match("/пр\z/mu", $stroka) ) { // условие также будет верным при "/юя\z/mu"
	echo 'В тексте присутствует строка, оканчивающаяся на "пр"';
} else {
	echo 'Соответствий не найдено.';
}

Специальные символы (метасимволы)

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

А вот и остальные метасимволы ., *, ?, {, }, [, ], +, \, |, (, ). Мы рассмотрим их в процессе этого урока, а сейчас важно, чтобы вы понимали, что они из себя представляют.

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

<?php
$stroka = '2+2=4';
 
// экранирование происходит при помощи обратного слэша \
if(preg_match("/^2\+2/", $string))
	echo 'Строка начинается с 2+2';

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

Квадратные скобки [ ]

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

Обратите внимание, что такие интервалы символов означают только 1 символ, принадлежащий этому интервалу.

$stroka = 'маг';
 
// для русских букв не забываем модификатор /u
echo preg_match("/м[a-к]г/u", $stroka);

Этот пример вернет 1 как для «маг», так и например для «миг».

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

Но есть и исключения, куда уж без них — если внутри квадратных скобок первым указать символ каретки ^, то он будет означать отнюдь не начало строки, а несоответствие набору символов, например [^б] — будет значать любой символ, кроме «б», [^а-и] — любой символ, не находящийся в промежутке «а-и». Отсюда пример:

$stroka = 'абвгдеёжзиклмнопрстуфхцчшщъыьэюя';
 
// для того, чтобы функция не просто возвращала 1, мы добавим в неё третий аргумент, переменную, в которую запишется первое соответствие
preg_match("/[^а-д]/u", $stroka, $matches);
 
// переменная $matches будет содержать первое соответствие - букву "е"
foreach( $matches as $key=>$value ) {
	echo $key.' -> '.$value; // 0 -> e
}

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

$stroka = 'абвгдеёжзиклмнопрстуфхцчшщъыьэюя';
 
preg_match_all("/[^а-д]/u", $stroka, $matches);
 
// элемент $matches[0] будет содержать массив(!) из соответствующих символов, каждый символ - отдельный элемент массива
foreach( $matches[0] as $symbol ) {
	echo $symbol;
}
// в итоге получится еёжзиклмнопрстуфхцчшщъыьэюя

Фигурные скобки { }

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

$stroka = 'PHP123'; 
 
echo preg_match("/PHP[0-9]{3}/", $stroka);

Точка .

Точка обозначает любой один символ, кроме переходов на новую строку \n или \r.

$stroka = 'этот маг';
 
// выведет 1, то есть совпадение найдено, но без флага /u работать как надо не будет
echo preg_match("/м.г/u", $stroka);

Астериск *

Звёздочка означает любое количество символа, стоящего перед ней (в том числе 0). Поясню на примере.

$stroka = 'php'; 
 
// будет выведена 1 как для "php", так для "pp", "phhp", "phhhhhhhp"
echo preg_match("/ph*p/", $stroka);

Плюс +

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

Знак вопроса ?

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

$stroka = '123-567'; 
 
// будет выведена 1, а также в том случае, когда дефис в строке будет отсутствовать.
echo preg_match("/123-?567/", $stroka);

Круглые скобки ( ) и прямая черта |

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

$stroka = "Привет, мир!";
 
// try to match the patterns This OR That OR There
echo preg_match("/^(Привет|Здравствуй|Хай)/", $stroka);

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

$stroka = "Привет, мир!";
 
// try to match the patterns This OR That OR There
preg_match("/^(Привет|Здравствуй|Хай), мир/", $stroka, $matches);
 
foreach($matches as $key=>$value) {
	echo $key.'->'.$value.'<br />';
}
/*
В результате получим
0->Привет, мир
1->Привет
То есть первый элемент массива - это найденная подстрока, подходящая под шаблон, а второй - какое именно условие подошло.
*/

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Пишите, если нужна помощь с сайтом или разработка с нуля.

Комментарии — 2

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

Миша Рудрастых и WordPress

Полезности из мира WordPress и жизни студии.

Мой телеграм-канал