ресурс для начинающих веб-разработчиков
комплексные веб-услуги по созданию сайтов

Справочный материал по основным языкам программирования и верстки сайтов.

Готовая методика создания простых и сложных динамичных сайтов, с использованием PHP и MySQL.

Использование веб-редактора Adobe Dreamweaver в разработке сайтов.

Использование графических редакторов Adobe Flash, Adobe Photoshop, Adobe Fireworks в подготовке веб-графики.

Разработка веб-сайтов под "ключ".

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

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

Регулярные выражения

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

Базовый синтаксис и создание регулярных выражений

В настоящий момент существует несколько диалектов регулярных выражений. В данный момент будет рассмотрен синтаксис 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 — любая десятичная цифра;
  • \D — любой символ, кроме десятичной цифры;
  • \s — любой пробельный символ;
  • \S — любой непробельный символ;
  • \w —любой символ образующий "слово";
  • \W — любой символ не образующий "слово";
  • \t — символ табуляции;
  • \f — конец файла;
  • \n — символ перевода строки;
  • \\ — символ обратного слеша (\);
  • \. — символ точки (".").

Рассмотренное выше регулярное выражение для числа можно записать следующим образом:

"/[\d]/"

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

"[^0-9]"

Это регулярное выражение отвечает любому символу, не содержащимуся в диапазоне 0-9, т.е. все что угодно, только не цифра.

Классы символов \d, \s и т.п. могут применяться в любой части регулярного выражения, а не только в квадратных скобках, т.е. вполне допустимо выражение вида "/\d/".

Выражения в квадратных скобках соответствует только одному символу и часто принимается совместно с так называемыми квантификаторами. Это символы ?, +, *, которые следуют сразу за символом и изменяют число вхождений конкретного символа в строку:

  • ? — символ либо входит в строку один раз, либо вообще в нее не входит;
  • * —любое вхождение символа в строку, в том числе и 0;
  • + — одно или более вхождений символа в строку;

Символ ? позволяет сократить выражение вида

"программирование|программирование \/РНР/i"

до

"/программирование (РНР)?/i"

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

"/[\d]+/"

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

"/^[\d]*S/"

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

Помимо круглых и квадратных скобок в регулярных выражениях так же применяются фигурные скобки {}. Они предназначены для указания чисел или диапазона чисел повторения элемента:

  • "xy{2}" — cоответствует строке "xyy";
  • "xy{2,}" — соответствует строке, в которой за х следует не менее двух у (может быть и больше);
  • "xy{2,6}" — соответствует строке, в которой за х следует от 2 до 6 у.
  • Для указания колличества вхождений не одиночного символа, а их последовательности, используются круглые скобки:

  • "x(yz){2,6}" — cоответствует строке, в которой за х следует от двух до шести последовательностей yz;
  • "x(yz)*" — 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>";

    }
    ?>

    В окне веб-браузера это будет выглядеть ТАК.

  • preg_replace (mixed pattern, mixed replacement, mixed subject [,int limit]) — ищет в строке subject соответствия регулярному выражению pattern, и заменяет их на replacement. Необязательного параметр limit задает число соответствий, которые надо заменить. Если этот параметр не указан, или равен -1, то заменяются все найденные соответствия.
  • Параметр 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 возвращает строку, в которой будет произведена замена.
  • preg_split() — разбивает строку по регулярному выражению. Синтаксис функции:
  • 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="+Иванов+++Москва+++++ridites@yndex.ru";
    $fields = preg_split("/\+{1.}/", $user_info);
    for($x=0;$x < sizeof($fields);$x++){
    print $fields[$x]. "<br>";
    }
    ?>

    В окне веб-браузера это будет выглядеть ТАК.