Регулярные выражения — это специализированный язык поиска и осуществление манипуляций с подстроками в тексте. Синтаксис регулярных выражений является достаточно сложным и его изучение требует серьезных усилий.
В настоящий момент существует несколько диалектов регулярных выражений. В данный момент будет рассмотрен синтаксис Perl-совместимых регулярных выражений, как самого распространенного и развитого диалекта.
Регулярное выражение — это шаблон, применяемый к заданному тексту слева направо. Большая часть символов сохраняет свое значение в шаблоне и означает совпадение с соответствующим символом. Так регулярное выражение содержащее обычный текст, например "грам", соответствует строке, содержащей указанную подстроку, например "программирование".
В Perl для регулярного выражения обязательно задание границ. Так приведенный выше пример можно написать следующим образом:
"/грам/"
Символ / применяется для задания границ регулярного выражения, т.е регулярное выражение действует до тех пор, пока не встретит второй символ прямого слеша(/). После регулярного выражения следуют модефикаторы шаблона — инструкции, действующие на все регулярное выражение. Мы рассмотрим только один модефикатор i. При его использовании поиск по регулярному выражению осуществляется без учета регистра. Так рассмотренный выше пример можно записать следующим образом:
"/грам/i"
Данное выражение будет соответствовать как строке "программирование", так и строке "ПРОГРАММИРОВАНИЕ".
Остальными модефикаторами можно ознакомиться в документации РНР, которая доступна для свободной загрузки с адреса http://www.php.net. Данный раздел документации переведен на русский язык.
Рассмотренное регулярное выражение осуществляет поиск по всему тексту, но чаще следует привязать регулярное выражение к началу слова, т.е. чтобы регулярное выражение "/грам/i" соответствовало строке, начинающейсясо слова "граммпластинка", но не подходило бы слову "программировние". Для этого используется символ ^, соответствующий началу строки:
"/^грам/i"
Знак доллара $ означает конец строки:
"/^граммпластинка$/i"
Это регулярное выражение соответствует любой строке "граммпластинка", но не подходит строке "граммпластинка — это вам не программирование", т.к. после искомого слова идет текст.
Регулярное выражение
"/^$/i"
соответствует пустой строке.
В поисковой строке может понадобиться найти подстроку, содержащую символ /, который у нас используется для обозначения границ. В этом случае необходимо прибегнуть к экранированию этого символа с помощью символа обратного слеша (\). Так у подстроки "Программирование/ РНР" регулярное выражение выглядит так:
"/программирование\ /php/i"
Eсли символ /встречается часто в поисковой строке (например, в HTML-тексте), то можно изменить границы регулярного выражения, в качестве них может выступать любой другой символ, например, следующее регулярное выражение эквивалентно только что рассмотренному:
"|программирование/php|i"
Использование символа вертикальной черты (|) в качестве границы слова не всегда приемлемо, т.к. он может присутствовать в регулярном выражении для задания альтернативных масок:
"/abc|абв/"
Этому регулярнову выражению соответствует любая строка, содержащая подстроки "abc" или "абв". Вертикальную черту удобно применять при проверке расширений и имен файлов, зон доменных имен и т.д. К примеру, следующее регулярное выражение проверяет, содержатся ли в строке подстроки "ru", "com" или "net":
"/ru|com|net/"
Это выражение соответствует любой строке, которая содержит подстроку abc.
Подстроки регулярных выражениях можно групперовать при помощи скобок:
"/домен - (ru|com|net)/i"
Это регулярное выражение будет соответствовать строке вида "домен - ru", вместо ru может быть как com, так и net. Если необходимо использовать скобки как часть искомой строки, их следует экранировать. Так для поиска подстроки "программирование (РНР)" следует использовать следующее регулярное выражение:
"/программирование \(РНР\)i"
Скобки при программировании в РНР и Perl имеют еще одно значение помимо группировки символов. Все найденные в скобках выражения сохраняются интерпретатором, и к ним можно обратиться при замене или поиске по номеру скобки \\1, \\2 и т.д.
Для задания класса символов используются квадратные скобки ([ ]).Они ограничивают поиск теми символами, в которые они заключены:
"/[abc]/"
Этому регулярному выражению соответствует подстрока, содержащая один символ: либо а, либо b, либо с.
Так для создания регулярного выражения, соответствующего всем буквам русского алфавита, можно, конечно, перечислить все буквы в регулярном выражении. Это допустимо, но утомительно. Более коротко такое регулярное выражение можно записать следующим образом:
"/[а-Я ]/"
Данное выражение подходит всем буквам русского алфавита, поскольку любые два символа, разделяются дефисом, задают соответствие диапазону символов, находящихся между ними. Регулярное выражение "/[а-Я ]/" описывает символы как нижнего, так и верхнего регистров, поэтому более подробно это выражение можно записать так:
"/[а-яА-Я ]/"
Точно таким же образом задаются регулярные выражения, соответствующие цифре:
"/[0-9 ]/" или
"/[0123456789]/"
Оба выражения эквивалентны.
В регулярных выражениях действуют также экранирование, применение обратного слеша с определенными символами, что приводит к их специальной интерпретации:
Рассмотренное выше регулярное выражение для числа можно записать следующим образом:
"/[\d]/"
Для исключения класса символов из поиска первым ставится символ ^, который в квадратных скобках действует уже не как указатель границы строки, а как отрицание:
"[^0-9]"
Это регулярное выражение отвечает любому символу, не содержащимуся в диапазоне 0-9, т.е. все что угодно, только не цифра.
Классы символов \d, \s и т.п. могут применяться в любой части регулярного выражения, а не только в квадратных скобках, т.е. вполне допустимо выражение вида "/\d/".
Выражения в квадратных скобках соответствует только одному символу и часто принимается совместно с так называемыми квантификаторами. Это символы ?, +, *, которые следуют сразу за символом и изменяют число вхождений конкретного символа в строку:
? — символ либо входит в строку один раз, либо вообще в нее не входит;
* —любое вхождение символа в строку, в том числе и 0;
Символ ? позволяет сократить выражение вида
"программирование|программирование \/РНР/i"
до
"/программирование (РНР)?/i"
Метасимвол + обозначает один или несколько экземпляров элемента непосредственно предшествующего элемента, а * — любое количество экземпляров элемента, в том числе и нулевое. Так, если необходимо найти подстроку, содержащую одну или более цифр, следует воспользоваться выражением вида
"/[\d]+/"
Cимвол * используется для любого числа вхождений строки в подстроку, т.е. регулярное выражение
"/^[\d]*S/"
соответствует пустой строке, либо строке, содержащей только цифры, причем их колличество не ограничено.
Помимо круглых и квадратных скобок в регулярных выражениях так же применяются фигурные скобки {}. Они предназначены для указания чисел или диапазона чисел повторения элемента:
"xy{2}" — cоответствует строке "xyy";
"xy{2,}" — соответствует строке, в которой за х следует не менее двух у (может быть и больше);
Для указания колличества вхождений не одиночного символа, а их последовательности, используются круглые скобки:
"x(yz){2,6}" — cоответствует строке, в которой за х следует от двух до шести последовательностей yz;
preg_match(string pattern, string subject [, array matches [, int flags [, int offset]]]) — осуществляет поиск в строке по регулярному выражению. Ищет в строке subject соответствие регулярному выражению pattern. Если задан необязательный параметр matches, то результаты поиска помещаются в массив. Элемент $matches[0] будет содержать часть строки, соответствующей вхождению всего шаблона, $matches[1] — часть строки соответствующей первым круглым скобкам, $matches[2] — вторым и т.д. Необязательный флаг flag может принять единственное значение PREG_OFFSET_CAPTURE, при указании которого изменяется формат возвращаемого массива $matches — каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение. Поиск осуществляется слева направо, с начала строки. Дополнительный параметр offset может быть использован для указания альтернативной начальной позиции для поиска. Функция preg_match() возвращает количество найденных соответствий. Это может быть 0(совпадения не найдены) и 1, поскольку preg_match() прекращает свою работу после первого найденного совпадения.
Пример1:
<?php
$str = "PHP один из лучших языков программирования для Web";
if (preg_match ("/php/i", $str))
{
echo("Соответствие найдено");
}
else
{
echo("Соответствие не найдено");
}
?>
В окне веб-браузера это будет выглядеть ТАК.
Пример2:
<?php
$str = "PHP один из лучших языков программирования для Web";
if (preg_match ("/\bweb\b/i", $str))
{
echo("Соответствие найдено");
}
else
{
echo("Соответствие не найдено");
}
?>
В окне веб-браузера это будет выглядеть ТАК.
Пример3:
<?php
// получаем www-адрес (имя хоста) из url
$url = "http://www.php.net/download.html";
preg_match("/^(http:\/\/)?([^\/]+)/i", $url, $matches);
$host = $matches[2];
echo("www-адрес: $host");
echo("<br>");
// получаем последние два сегмента имени хоста (доменное имя)
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "доменное имя: {$matches[0]}\n";
?>
В окне веб-браузера это будет выглядеть ТАК.
Если необходимо найти либо сосчитать все совпадения, следует воспользоваться функцией preg_match_all().
preg_match_all(string pattern, string subject, array matches [, int flags [, int offset]]) — ищет в строке subjec все совпадения с регулярным выражением pattern и помещает результат в массив matches в порядке, определяемом комбинацией флагов flags. Так же как в случае функции preg_match(), можно задать смещение offset, начиная с которого будет осуществляться поиск в строке subjec.
После нахождения первого соответствия последующие поиски будут осуществлться не с начала строки, а от конца последнего найденного вхождения.
Дополнительный параметр flags может комбинировать следующие значения (использование PREG_PATTERN_ORDER одновременно с PREG_SET_ORDER бессмысленно):
PREG_PATTERN_ORDER — если этот флаг установлен, результат будет упорядочен следующим образом: элемент $matches[0] содержит массив полных вхождений регулярных выражений, элемент $matches[1] хранит массив вхождений первых круглых скобок, $matches[2] — вторых и т.д. То есть если строка содержит три соответствия регулярному выражению, то подстроку для последнего соответствия всему регулярному выражению можно найти в элементе $matches[0] [3], а для первых круглых скобок данного соответствия — в элементе $matches[1] [3];
PREG_SET_ORDER — если этот флаг установлен, результат будет упорядочен следующим образом: элемент $matches[0] содержит полный набор вхождений, элемент $matches[1] — второй набор вхождений и т.д. В таком случае массив $matches[0] содержит первый набор вхождений, а именно: элемент $matches[0][0] хранит первое вхождение всего регулярного выражения, элемент $matches[0][1] — первое вхождение первых круглых скобок, $matches[0][2] — вторых и т.д. Аналогично массив $matches[1] содержит второй набор вхождений, и так для каждого найденного набора;
PREG_OFFSET_CAPTURE — в случае, если флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что данный флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение.
Пример:
<?php
$user_info = "<b>PHP</b> <br> один из лучших языков программирования для <b>Web</b>";
preg_match_all ("/<b>(.*)<\/b>/e", $user_info, $pat_array);
print $pat_array[0][0]. "<br>".$pat_array[0][l];
?>
В окне веб-браузера это будет выглядеть ТАК.
Функция preg_match() возвращает количество найденных вхождений шаблона (может быть нулем) либо false, если во время выполнения возникли какие-либо ошибки.
Обобщением функций preg_match() и preg_match_all() является функция preg_grer().
array preg_grer(string pattern, array input [, int flags]) — перебирает все элементы заданного массива и возвращает все элементы, в которых совпадает заданное регулярное выражение. Возвращает массив, состоящий из элементов массива input, которые соответствуют заданному регулярному выражению pattern. Параметр flags может принимать единственное значение PREG_GREP_INVERT, задание которого приводит к тому, что функция возвращает те элементы массива input, которые не соответствуют регулярному выражению pattern.
Пример:
<?php
$avto=array("Nissan", "Волга", "Ваз");
/*поиск элементов начинающихся на "в" зa которым следует один или несколько символов*/
$b_avto=preg_grep("/в(\w+)/i", $avto);
for ($х = 0; $x <sizeof($avto); $x++){
print $b_avto[$x]. "<br>";
}
?>
В окне веб-браузера это будет выглядеть ТАК.
Параметр replacement может содержать ссылки вода \\n. Каждая такая ссылка будет заменена на подстроку, соответствующую n раз повторяющимся круглым скобкам, n может принять значение от 0 до 99, причем ссылка на \\0 соответствует вхождению всего шаблона. Выражения в круглых скобках нумеруются слева направо, начиная с единицы.
Если во время выполнения функции были обнаружены совпадения с шаблоном, будет возвращено измененное значение subjec, в противном случае будет возвращен исходный текст subjec.
Первые три параметра функции preg_replace() могут быть одномерными массивами. В случае если массив использует ключи, при обработке массива они будут взяты в том порядке, в котором расположены в массиве.
Если параметры pattern и replacement являются массивами, preg_replace() поочередно извлекает из обоих массивов по паре элементов и использует их для операции поиска и замены. Если массив replacement содержит больше элементов, чем pattern, вместо недостающих элементов для замены будут взяты пустые строки. В случае, если pattern является массивом, а replacement — строкой, по каждому элементу массива pattern будет осуществлен поиски замена на pattern (шаблоном будут поочередно все элементы массива, в то время как строка замены остается фиксированной). Вариант, когда pattern является строкой, а replacement — массивом, не имеет смысла.
Пример:
<?php
$str = "Февраль 23, 2009";
$pattern = "/(\w+) (\d+), (\d+)/i";
$replacement = "23 \${1} \$3";
print preg_replace($pattern, $replacement, $str);
?>
В окне веб-браузера это будет выглядеть ТАК.
preg_replace_callback(mixed pattern, callback callback, mixed subject [, int limit]) — осуществляет поиск по регулярному выражению и замену с использованием функции обратного вызова. Поведение этой функции во многом сходно с preg_replace(), за исключением того, что вместо параметра replacemen необходимо указать функцию callback, которой в качестве входящего параметра передается массив найденных вхождений. Функция обратного вызова callback возвращает строку, в которой будет произведена замена.
array preg_split (string шаблон, string строка [, int порог [, int флаги]])
Функция возвращает массив, состоящий из подстрок заданной строки строка, которая разбита по границам, соответствующим шаблону шаблон.
В случае если параметр порог указан, функция возвращает не более, чем порог подстроек, при его отсутствии или равенстве — 1 функция действует без ограничений. Последний параметр флаги может быть произвольной комбинацией следующих флагов (соединение происходит при помощи оператора ИЛИ (|)):
PREG_SLIT_NO_EMPTY — если этот флаг указан, функция preg_split() вернет только пустые подстроки;
PREG_SLIT_DELIM_CAPTURE — если этот флаг указан, выражение, заключенное в круглые скобки в разделяющем шаблоне, также извлекается из заданной строки и возвращается функцией;
PREG_SLIT_OFFSET_CAPTURE — если флаг задан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом — смещение.
Пример:
<?php
$user_info="+Иванов+++Москва[email protected]";
$fields = preg_split("/\+{1.}/", $user_info);
for($x=0;$x < sizeof($fields);$x++){
print $fields[$x]. "<br>";
}
?>
В окне веб-браузера это будет выглядеть ТАК.
Похожие материалы по теме: Регулярные выражения