Квартиры, дома, земельные участки Краснодарского края без посредников. Объявления собственников недвижимости.
Реклама здесь

Поиск по сайту



PHP Поиск



Стоматологический центр в Москве - зубы стоматология.

Регулярные выражения (regexp).

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

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

<набор символов><квантификатор>

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

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

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

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

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

POSIX.

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

.точкалюбой символ
[<символы>]квадратные скобкикласс символов ("любое из")
[^<символы>] негативный класс символов ("любое кроме")
-тиреобозначение последовательности в классе символов ("[0-9]" — цифры)

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

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

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

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

либо

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

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

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

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

Якоря

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

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

ereg("foo$", $bar)

Структура

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

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

if (ereg("[a-z]+|[A-Z]+|[0-9]+", $text)) ...
Вертикальная черта — знак "или" регулярных выражений (знака "и", естественно, не существует — это и есть само регулярное выражение). Разделенные вертикальной чертой шаблоны в официальной документации называются альтернативными ветвями (это подразумевает ветвление, т.е. наличие вложенных альтернативных ветвей). Программа сравнивает со строкой все ветви (проходясь по их ряду слева направо), до первого совпадения (это важно учесть, если у вас сложное выражение со вложенными ветвями). Для разделения уровней и отделения этого дерева альтернатив от остального шаблона используются обычные скобки. Если те же большие/маленькие буквы/цифры надо искать внутри контейнера тегов:
if (ereg("<tag>([a-z]+|[A-Z]+|[0-9]+)</tag>", $text)) ...
Скобки называются subpattern (вложенный шаблон). И используются не только для сложных вариантов шаблонов, но и для гибкой замены фрагментов текста или получения их в переменную. К примеру, для печатной версии текста дублируем адреса ссылок текстом в скобках:
ereg_replace("<a href=([^>]+)>[^<]+</a>", "  [1]", $text);
Первые скобки — первый вложенный шаблон — можно получить "на выходе" через обозначение "n" (поскольку обратный слэш в php и многих других языках используется для спецсимволов, надо поставить перед ним еще один такой же, чтобы прогамма понимала его буквально). Под нулевым номером — вся совпавшая строка. У себя в печатной версии статьи я не пишу ссылки сразу в тексте, а делаю их список в конце примерно так:

if (ereg("<a href=([^>]+)>([^<]+)</a>", $text, $match)) {
for ($a=0;$a<sizeof($match[0]);$a++) {
    $b = $a+1;
    $text = str_replace($match[0][$a], $match[0][$a]." [$b]", $text);
    $match[1][$a] = "$b) ". $match[1][$a];
    };
  $text .= "<br><h2>Ссылки, использованные в выпуске:</h2>".
  		implode("<br>", $match[1]);
  };

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

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

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

2. Поиск по базе данных [3]: из пользовательского поискового запроса делается sql-запрос. Если отбросить создание статистики поиска (сколько найдено всего, сколько по каждому слову), то получится, что необходимо всего 6-7 строк кода. Там же описана и подсветка слов в результатах поиска. Кстати, важное замечание: перед тем, как вырезать короткие слова из строки я заменяю пробелы между словами на двойные. Почему? Потому что совпадающие с шаблоном строки не должны наезжать друг на друга.

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

3. Как хранить новости в файлах и не бегать циклом по дате:

$handle=opendir($newsdir);
while ($file = readdir($handle)) {
  if (is_file($file) && ereg("^[0-9]{6}.txt$", $file))
    print ("<p align=justify><b>". 
    	ereg_replace("^([0-9]{2})([0-9]{2})([0-9]{2}).txt$", 
	  "1.2.203", $file). "</b> ". implode("", file($file)). "</p>");
closedir($handle);

4. Проверка правильного написания email-а:

if (!eregi("^[a-z0-9._-]+@[a-z0-9._-]+.[a-z]{2,4}$", $email))
  print("Bad email: "$email"");

PCRE

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

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

.*?

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

$text = ereg_replace("<a +href=([^>]+)>[^<]+</a>", " [1]", $text);

То есть, внури ссылки не должно быть тегов (например "<a href=...><b>...</b></a>"). Если же сделать так:

$text = ereg_replace("<a +href=([^>]+)>.*</a>", " [1]", $text);

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

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

$text = preg_replace("/<as+href=(.*?)>.*?</a>/", " [1]", $text);

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

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

w[a-z0-9]
W[^a-z0-9]
s[ ]
S[^ ]

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

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

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

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

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

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

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

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

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

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

preg_grep

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

Синтаксис

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

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

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

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

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


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

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

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

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

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

Пример кода

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

Пример кода

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

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

Пример кода

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

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

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

domain name is: php.net

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] содержит массив вхождений первой подмаски, и так далее.

Пример кода

<?php
preg_match_all
("|<[^>]+>(.*)</[^>]+>|U"
    
"<b>example: </b><div align=left>this is a test</div>"
    
$outPREG_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] содержит второй набор вхождений, и так далее.

Пример кода

<?php
preg_match_all
("|<[^>]+>(.*)</[^>]+>|U"
    
"<b>example: </b><div align=\"left\">this is a test</div>"
    
$outPREG_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
В случае, если этот флаг указан, для каждой найденной подстроки будет указана ее позиция в исходной строке. Необходимо помнить, что этот флаг меняет формат возвращаемых данных: каждое вхождение возвращается в виде массива, в нулевом элементе которого содержится найденная подстрока, а в первом - смещение. Данный флаг доступен в PHP 4.3.0 и выше.


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

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

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

Пример кода

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

Пример кода

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

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

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

for (
$i=0$icount($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] . "\n\n";
}
?>

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


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 функциях. Наиболее распространенным ограничителем является символ '/'.

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

Пример кода

<?php
$keywords 
"$40 for a g3/400";
$keywords preg_quote($keywords"/");
echo 
$keywords// возвращает \$40 for a g3\/400
?>

Пример кода

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

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.

Пример кода

<?php
$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() для каждого из массивов.

Пример кода

<?php
// Использование массивов с числовыми индексами в качестве аргументов
// функции 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(), получаем желаемый результат:

Пример кода

<?php
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(), возникнет ошибка синтаксиса.

Пример кода

<?php
// Замена по нескольким шаблонам
$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


Пример кода

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


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

Пример кода

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

$search = array ("'<script[^>]*?>.*?</script>'si",  // Вырезает javaScript
                 
"'<[\/\!]*?[^<>]*?>'si",           // Вырезает HTML-теги
                 
"'([\r\n])[\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 функцию, которой в качестве входящего параметра передается массив найденных вхождений. Ожидаемый результат - строка, которой будет произведена замена.

Пример кода

<?php
  
// Этот текст был использован в 2002 году
  // мы хотим обновить даты к 2003 году
  
$text "April fools day is 04/01/2002\n";
  
$text.= "Last christmas was 12/24/2001\n";

  
// функция обратного вызова
  
function next_year($matches
  {
    
// как обычно: $matches[0] -  полное вхождение шаблона
    // $matches[1] - вхождение первой подмаски,
    // заключенной в круглые скобки, и так далее...
    
return $matches[1].($matches[2]+1);
  }

  echo 
preg_replace_callback(
              
"|(\d{2}/\d{2}/)(\d{4})|",
              
"next_year",
              
$text);

  
// результат:
  // April fools day is 04/01/2003
  // Last christmas was 12/24/2002
?>


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

Пример кода

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

Пример кода

<?php
// Получение подстрок из заданного текста
// разбиваем строку по произвольному числу запятых и пробельных символов, 
// которые включают в себя  " ", \r, \t, \n и \f
$keywords preg_split("/[\s,]+/""hypertext language, programming");
?>

Пример кода

<?php
// Разбиваем строку на составляющие символы
$str = 'string';
$chars preg_split('//', $str, -1PREG_SPLIT_NO_EMPTY);
print_r($chars);
?>

Пример кода

<?php
$str 
= 'hypertext language programming';
$chars preg_split('/ /', $str, -1PREG_SPLIT_OFFSET_CAPTURE);
print_r($chars);
?>

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

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


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

Популярное:


Содержание:


Новое за неделю



Сейчас на сайте: 489