- Регулярные выражения. Часть 1. Введение. Специальные символы.
- Основы основ
- Небольшое отступление про русские буквы
- Верхний регистр букв
- Поиск соответствия в начале строки, символ ^
- Поиск соответствия концу строки. В чём отличие между \z и $
- Специальные символы (метасимволы)
- Квадратные скобки [ ]
- Точка .
- Астериск *
- Плюс +
- Знак вопроса ?
- Круглые скобки ( ) и прямая черта |
- Миша
- preg_match
- Список параметров
- Возвращаемые значения
- Список изменений
- Примеры
- Примечания
- Смотрите также
Регулярные выражения. Часть 1. Введение. Специальные символы.
Наконец-то я добрался до этой статьи, в ней я попытаюсь с нуля рассказать про регулярные выражения в PHP. Для начала — что это такое?
Если в двух словах и понятным языком, то регулярные выражения — это метод, основанный на соответствии строки заданному шаблону.
Основы основ
Как я уже сказал, начну с самого нуля. Недаром же я пометил эту статью тегом «Начинающим».
А начинается всё со строки в PHP.
// создаем строку $stroka = 'abcdefghijklmnopqrstuvwxyz0123456789'; // выводим строку echo $stroka;
Если нам сперва нужно определить, находится ли abc внутри нашей строки, и только тогда вывести её, то попробуем сделать что-то подобное:
// та же самая строка $stroka = 'abcdefghijklmnopqrstuvwxyz0123456789'; if( preg_match("/abc/", $stroka) ) { // возвратит 1 в случае положительного результата (abc
внутри строки) echo $stroka; }
Код выше дан исключительно для примера, потому что это не самый оптимальный вариант поиска вхождения в строке, для этого лучше использовать PHP-функции strpos() или strstr() .
Небольшое отступление про русские буквы
Хочу обратить ваше внимание, регулярные выражения PHP по умолчанию не поддерживают русские буквы и поэтому далеко не все примеры будут работать корректно, однако это легко исправляется модификатором /u (дальше всё объясню), который включает дополнительную функциональность: шаблон и строки станут обрабатываться как UTF-8 (доступно с версии PHP 4.1.0).
Подробно в следующем примере.
Верхний регистр букв
Символы верхнего и нижнего регистра — не одно и то же. Однако чувствительность к регистру можно отключить при помощи модификатора /i . Модификаторы добавляются в конце шаблона, смотрите пример:
// строку оставляем пока что ту же $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 , мы должны экранировать + .
$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("/PHP1/", $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.'
'; } /* В результате получим 0->Привет, мир 1->Привет То есть первый элемент массива - это найденная подстрока, подходящая под шаблон, а второй - какое именно условие подошло. */
Миша
Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.
Пишите, если нужна помощь с сайтом или разработка с нуля.
preg_match
Ищет в заданном тексте subject совпадения с шаблоном pattern .
Список параметров
В случае, если указан дополнительный параметр matches , он будет заполнен результатами поиска. Элемент $matches[0] будет содержать часть строки, соответствующую вхождению всего шаблона, $matches[1] — часть строки, соответствующую первой подмаске, и так далее.
flags может принимать значение следующего флага: PREG_OFFSET_CAPTURE В случае, если этот флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемого массива matches в массив, каждый элемент которого содержит массив, содержащий в индексе с номером 0 найденную подстроку, а смещение этой подстроки в параметре subject — в индексе 1.
Обычно поиск осуществляется слева направо, с начала строки. Можно использовать дополнительный параметр offset для указания альтернативной начальной позиции для поиска (в байтах).
Замечание:
Использование параметра offset не эквивалентно замене сопоставляемой строки выражением substr($subject, $offset) при вызове функции preg_match() , поскольку шаблон pattern может содержать такие условия как ^, $ или (?<=x). Сравните:
$subject = «abcdef» ;
$pattern = ‘/^def/’ ;
preg_match ( $pattern , $subject , $matches , PREG_OFFSET_CAPTURE , 3 );
print_r ( $matches );
?>?php
Результат выполнения данного примера:
В то время как этот пример
$subject = «abcdef» ;
$pattern = ‘/^def/’ ;
preg_match ( $pattern , substr ( $subject , 3 ), $matches , PREG_OFFSET_CAPTURE );
print_r ( $matches );
?>?php
Array ( [0] => Array ( [0] => def [1] => 0 ) )
Возвращаемые значения
preg_match() возвращает 1, если параметр pattern соответствует переданному параметру subject , 0 если нет, или FALSE в случае ошибки.
Эта функция может возвращать как boolean FALSE , так и не-boolean значение, которое приводится к FALSE . За более подробной информацией обратитесь к разделу Булев тип. Используйте оператор === для проверки значения, возвращаемого этой функцией.
Список изменений
Версия | Описание |
---|---|
5.3.6 | Возвращает FALSE если offset больше, чем длина subject . |
5.2.2 | Именованные подмаски теперь позволяют синтаксис (?) и (?’name’), также как и (?P). Предыдущие версии позволяли только (?P). |
Примеры
Пример #1 Поиск подстроки «php» в тексте
// Символ «i» после закрывающего ограничителя шаблона означает
// регистронезависимый поиск.
if ( preg_match ( «/php/i» , «PHP is the web scripting language of choice.» )) echo «Вхождение найдено.» ;
> else echo «Вхождение не найдено.» ;
>
?>?php
Пример #2 Поиск слова «web» в тексте
/* Специальная последовательность \b в шаблоне означает границу слова,
* следовательно, только изолированное вхождение слова ‘web’ будет
соответствовать маске, в отличие от «webbing» или «cobweb» */
if ( preg_match ( «/\bweb\b/i» , «PHP is the web scripting language of choice.» )) echo «Вхождение найдено.» ;
> else echo «Вхождение не найдено.» ;
>
?php
if ( preg_match ( «/\bweb\b/i» , «PHP is the website scripting language of choice.» )) echo «Вхождение найдено.» ;
> else echo «Вхождение не найдено.» ;
>
?>
Пример #3 Извлечение доменного имени из URL
// Извлекаем имя хоста из URL
preg_match ( ‘@^(?:http://)?([^/]+)@i’ ,
«http://www.php.net/index.html» , $matches );
$host = $matches [ 1 ];
?php
// извлекаем две последние части имени хоста
preg_match ( ‘/[^.]+\.[^.]+$/’ , $host , $matches );
echo «доменное имя: < $matches [ 0 ]>\n» ;
?>
Результат выполнения данного примера:
Пример #4 Использование именованных подмасок
/* Это также работает в PHP 5.2.2 (PCRE 7.0) и более поздних версиях,
* однако, вышеуказанная форма рекомендуется для обратной совместимости */
// preg_match(‘/(?\w+): (?\d+)/’, $str, $matches);
Результат выполнения данного примера:
Array ( [0] => foobar: 2008 [name] => foobar [1] => foobar [digit] => 2008 [2] => 2008 )
Примечания
Не используйте функцию preg_match() , если необходимо проверить наличие подстроки в заданной строке. Используйте для этого strpos() либо strstr() , поскольку они выполнят эту задачу гораздо быстрее.
Смотрите также
- «Регулярные выражения PCRE»
- preg_quote() — Экранирует символы в регулярных выражениях
- preg_match_all() — Выполняет глобальный поиск шаблона в строке
- preg_replace() — Выполняет поиск и замену по регулярному выражению
- preg_split() — Разбивает строку по регулярному выражению
- preg_last_error() — Возвращает код ошибки выполнения последнего регулярного выражения PCRE