Регулярные выражения — программируем текстовый поиск
24.10.08Мой Компьютер, №07 (511), 01.07.2008
Регулярные выражения — это средство, при помощи которого можно легко найти нужные фрагменты в текстовых данных. В отличие от функции strpos(), которая ищет конкретный текст, они основываются на использовании образцов для поиска. Образец, шаблон, паттерн (англ. pattern) — ключевое понятие в регулярных выражениях. Это некая сущность, которую мы ищем, но представленная не вербально (последний слэш в строке, номер телефона), а при помощи специального языка. На языке регулярных выражений можно представить практически любую текстовую конструкцию. В этом сила данного инструмента. В конце прошлого века регулярные выражения произвели настоящий прорыв в отрасли обработки текстовой информации.
Как и многие полезные вещи, регулярные выражения пришли из операционной системы UNIX. Существует их две разновидности — POSIX-совместимые (были разработаны первыми и сейчас считаются устаревшими) и Perl-совместимые (обладают более богатым синтаксисом, считаются более прогрессивными и сейчас наиболее популярны). Соответственно, последние мы и будем рассматривать.
Шаг 1. Начинаем с азов
Какой самый простейший паттерн? Нетрудно догадаться, что это паттерн, описывающий точно заданную строку символов. То есть паттерн abc найдет строку abc. В регулярных выражениях любой символ означает самого себя. Исключение составляют специальные метасимволы ( ^ $ . [ ] | ( ) ? * + { } -), которые, по сути, являются операторами языка регулярных выражений, а также символы-ограничители (/ или < >) паттерна.
Что же делать, если надо искать один из выше перечисленных символов? На помощь приходит наш старый знакомый слэш. Если его поставить перед метасимволом, то метасимвол теряет свой «служебный статус». Ну, а сам трудяга-слэш изображается в виде самого себя, но удвоенного: . Соответственно, для поиска сроки 1+1 паттерн будет 1+1, для поиска строки array[] — array[] и т.д.
Шаг 2.
Escape-последовательности
![]() |
Табл. 1 |
С алфавитно-цифровыми и служебными символами мы разобрались. Теперь представим ситуацию, когда нам надо найти какой-нибудь непечатный символ — пробел, табуляцию, перенос строки и т.п. Читатели, знакомые с языком C, сразу сообразят, что такие символы изображаются через escape-последовательности. Perl-совместимые регулярные выражения поддерживают следующие последовательности (табл. 1).
Шаг 3. Группы символов и повторения
Итак, мы рассмотрели, как в паттернах задаются конкретные символы и слова. Но, как говорилось, основная сила регулярных выражений в том, что они могут искать некоторую сущность, заданную не определенным текстом, а некоторыми общими характеристиками. Например, мы ищем в тексте номер телефона. Что общего у всех номеров телефона? Формат записи. Каждый номер телефона состоит из кода АТС (3 цифры) и двух двухзначных чисел, разделенных дефисами.
Итак, нам надо найти строку по следующему описанию: вначале идут три цифры, причем первая не ноль; затем тире; потом две цифры, потом опять тире, потом еще две цифры.
Для решения этой задачи нам надо уметь записывать:
- диапазон значений, который будет стоять на месте одного символа;
- количество повторений символа.
В Perl-совместимых регулярных выражениях для этого используются специальные метасимволы.
Для выбора из группы символов используются квадратные скобки, в которых и перечисляются возможные значения (без запятых между ними). Например, [abc] означает что символ может принимать значение a, b или c. Если нам надо цифры, то перечень будет следующим: [0123456789]. Наверняка вы скажете, что это слишком громоздкая запись. И будете правы. На самом деле можно записать намного проще, при помощи диапазона: [0-9]. В одной группе можно указывать несколько диапазонов, совмещать диапазоны и обычное перечисление значений: [A-Za-z], [0-9abc]. Какой угодно символ обозначается точкой: . (без квадратных скобок). Существуют также определенные обозначения для указания наиболее часто используемых групп символов (цифры, алфавитно-цифровые и т.д.), а также определенные нюансы в использовании символов – и ], но мы их рассмотрим в следующих статьях.
Для выбора количества повторений используется специальная конструкция метасимволов, именуемая квантификатором (англ. quantity — количество). Квантификатор записывается при помощи фигурных скобок {m,n}, где m — минимальное, а n — максимальное количество повторений символа. Например, запись [0-9]{2,3} означает, что мы ищем последовательность из двух или трех цифр. Верхнюю (но не нижнюю!) границу можно не указывать: [0-9]{2,} будет означать поиск последовательности двух и более цифровых знаков. Если надо найти точное количество символов, то надо указать только одно число без запятой ([0-9]{2} — ровно два цифровых знака).
Для наглядности напишу небольшую табличку квантификаторов (табл. 2).
![]() |
Табл. 2 |
Квантификатор {0,1} применяется для задания в паттерне символа или последовательности, которая может присутствовать, а может и не присутствовать в сущности, которую ищем. К примеру, если мы задаем паттерн для расширенной записи телефона с кодом страны и города, то плюс в начале номера, который может быть или не быть, будет обозначаться как +{0,1}.
ВНИМАНИЕ! КВАНТИФИКАТОРОВ ВИДА «ДО m РАЗ» ({,m}) НЕ СУЩЕСТВУЕТ. КОНСТРУКЦИЯ {,m} (где m — некоторое число) БУДЕТ ВОСПРИНЯТА КАК ОБЫЧНАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ СИМВОЛОВ!
Шаг 4. Конструируем регулярные выражения
Итак, мы уже знаем, как указать в паттерне диапазон значений, которые может принимать один символ и количество его повторений. Этих знаний достаточно, чтобы составлять простейшие паттерны.
Мы имеем некоторую сущность, которую хотим найти. В данном случае это номер телефона. Для того, чтобы записать паттерн в виде последовательности операций перечисления и повторения, мы саму сущность должны разбить на кусочки, в каждом из которых повторяются символы однородной группы (символы из одного диапазона). Удобно это делать, мысленно пробегая слева направо по строке, которую ищем, и выделяя такие однородные группы.
![]() |
Табл. 3 |
К примеру, для номера телефона — сначала идет код АТС, он состоит из трех цифр, первая из которых не нулевая. Тут две группы символов: один символ диапазона 1–9 и последовательность двух символов диапазона 0–9. На языке регулярных выражений это запишется как [1-9]{1}[0-9]{2}. После кода АТС идет дефис, следовательно, дописываем в паттерн обозначение дефиса (не забываем поставить слэш, т.к. это метасимвол): . И так далее. Подробный процесс создания паттерна для номера телефона приведен в таблице 3.
Шаг 5. Реализация на PHP
Итак, мы создали паттерн для поиска телефонного номера. Теперь вам уже, наверное, не терпится опробовать его на практике :-). Не волнуйтесь, сейчас перейдем к практической работе.
Для чего используются регулярные выражения? Да для тех же целей, что и функции strpos(), substr(), str_replace():
- проверка на соответствие образцу (например, проверка корректности введенного в форму телефона, е-mail и т.п.);
- извлечение из текста участков, соответствующих образцу (например, извлечь из текста письма клиента его телефон; извлечь из документа-отчета, содержащего отформатированные данные, отдельные поля и т.д.);
- замена в тексте участков, соответствующих образцу (например, вырезать из текста объявления ссылки, чтобы пользователи не могли рекламировать сайты через доску объявлений).
Для решения вышеуказанных задач, в PHP существуют функции preg_match(), preg_match_all(), preg_replace(). Сегодня мы кратко рассмотрим первые две из них.
Функция preg_match() проверяет, соответствует ли строка образцу, заданному паттерном.
Формат вызова:
mixed preg_match ( string $pattern , string $subject );
Если в строке есть хотя бы один участок, соответствующий паттерну, то функция вернет количество совпадений. Если совпадений нет — вернет 0. Если вы допустили в маске ошибку, на выходе функция выдаст FALSE.
Самые нетерпеливые, наверное, уже написали скрипт, ввели в качестве первого параметра наш паттерн, в качестве второго — любой номер телефона, запустили и… функция выдала ошибку :-). Дело в том, что в PHP паттерны необходимо заключать в специальные ограничители. Обычно для этих целей используются пары символов / / или < >. ВНИМАНИЕ! Если символ-ограничитель используется в паттерне, он должен быть «заслэшен»!
Возможности функции демонстрирует скрипт example1.php. Он проверяет, является ли введенное в поле формы значение номером телефона:
<?php
// если в поле формы был введен текст
if (isset($_REQUEST[«phone»]))
{
// выполняем проверку на соответствие регулярному выражению
if (preg_match(«/[1-9][0-9]{2}-[0-9]{2}-[0-9]{2}/», $_REQUEST[«phone»]))
// в тексте поля формы имеются совпадения с паттерном — следовательно, в нем содержатся
// номера телефонов
$result = «Введенный текст является номером телефона»;
else
// соответствий нет — текст не содержит номера телефонов
$result = «Введенный текст не является номером телефона»;
}
?>
<!—собственно сама HTML-форма —>
<form id=»checkform» name=»checkform» action=»example1.php» method=»post»>
<table width=»250″>
<tr>
<td>
Номер телефона:
</td>
<td>
<!— поле ввода —>
<input type=»text» id=»phone» name=»phone» size=»15″ value=»<?php echo $_REQUEST[«phone»]; ?>»>
</td>
</tr>
<tr>
<td colspan=»2″ align=»center»>
<input type=»submit» value=»Проверить»>
</td>
</tr>
</table>
</form>
<?php
// если в поле формы был введен текст
if (isset($_REQUEST[«phone»]))
{
?>
<br>
<?php
// выводим результат проверки
echo $result;
}
?>
Запускаем скрипт, вводим в поле разные значения и любуемся результатом (рис. 1, 2, 3):
![]() | ![]() | ![]() |
Рис. 1 | Рис. 2 | Рис. 3 |
Функция preg_match_all() позволяет извлечь из текста все соответствия паттерном.
Формат вызова:
int preg_match_all ( string $pattern , string $subject , array $&matches);
Функция ищет в строке subject все совпадения с шаблоном pattern и формирует из них массив matches. Формат этого массива может меняться в зависимости от наличия в шаблоне подвыражений (что такое подвыражения, вы узнаете в следующих статьях) и дополнительных параметров, переданных в функцию. Но в простейшем случае нулевой элемент массива matches будет массивом, содержащим все участки текста, которые совпали с паттерном.
Возможности функции демонстрирует скрипт example2.php. Он обрабатывает текст, введенный в область ввода формы, извлекает из него все телефоны и выводит на печать.
<?php
// если в поле формы был введен текст
if (isset($_REQUEST[«text»]))
{
// выполняем проверку на соответствие регулярному выражению
// и извлекаем все совпадения
if (preg_match_all(«/[1-9][0-9]{2}-[0-9]{2}-[0-9]{2}/», $_REQUEST[«text»], $matches))
{
// в тексте поля формы имеются совпадения с паттерном — следовательно, в нем содержатся
// номера телефонов
// нулевой элемент массива $matches содержит все совпадения.
// объединяем его элементы через запятую функцией implode() и добавляем
// к строке результата
$result = «Во введенном тексте содержатся следующие номера телефонов: «.implode(«, «, $matches[0]);
}
else
// соответствий нет — текс не содержит номера телефонов
$result = «Во введенном тексте нет номеров телефона»;
}
?>
<!—собственно сама HTML-форма —>
<form id=»checkform» name=»checkform» action=»example2.php» method=»post»>
<table width=»250″>
<tr>
<td>
Введите текст:
</td>
</tr>
<tr>
<td>
<!— поле ввода —>
<textarea id=»text» name=»text» style=»width:100%;» rows=»5″><?php echo $_REQUEST[«text»]; ?></textarea>
</td>
</tr>
<tr>
<td align=»center»>
<input type=»submit» value=»Проверить»>
</td>
</tr>
</table>
</form>
<?php
// если в поле формы был введен текст
if (isset($_REQUEST[«text»]))
{
?>
<br>
<?php
// выводим результат
echo $result;
}
?>
Запускаем скрипт, открываем страничку контактов какой-нибудь киевской фирмы, копируем ее содержимое, вставляем в поле ввода и любуемся результатом (рис. 4, 5).
![]() | ![]() |
Рис. 4 | Рис. 5 |
Итоги
Мы познакомились с регулярными выражениями, узнали, что это такое и с чем его едят, рассмотрели простейшие случаи их практического применения. В следующих статьях мы будем знакомиться с другими возможностями этого мощного инструмента. А пока потренируйтесь немного и попробуйте самостоятельно сконструировать и проверить следующие паттерны:
- шаблон мобильного номера (+380xxyyyyyyy или +38(0xx)yyyyyyy или +38(0xx)yyy yyyy или +38(0xx)yyy-yy-yy);
- универсальный шаблон телефонного номера (+код_страны(код города)номер). Предусмотрите возможность написания или ненаписания плюса, скобок, в которые заключен код города, и дефисов. Длина кода города не должна ограничиваться тремя символами;
- шаблон е-мейла (логин@сервер);
- шаблон URL (http://www.что-то_там) — «www» может либо быть, либо не быть.
Желаю вам успешно решить задания, и до встречи на страницах МК!
Алексей «CyberAdmin» СЕРДЮКОВ
Web-droid editor

вологість:
тиск:
вітер:

Огляд ноутбуку Lenovo ThinkPad X1 Extreme Gen 5: в чому сіль?



Ноутбуки Lenovo серії ThinkPad X1 Extreme мають бути готові до будь яких навантажень, витримувати певні фізичні випробовування та при цьому характеризуватися доволі невеликим габаритами та вагою. Розкажемо про модель п’ятого покоління та розберемося наскільки вона виправдовує свій статус екстремальної

Нова пошта запустила сервіс безкоштовного повернення товарів
події в Україні сервіс«Легке повернення». — це швидка та безкоштовна послуга для повернення товару або частини товарів із замовлення продавцю протягом 14 днів після отримання посилки.
Смартфон Samsung Galaxy F14 5G за $170 пропонує дисплей 90 Гц, чип Exynos 1330, потрійну камера 50 Мпікс і батарею 6000 мАг
Android Galaxy Samsung смартфонПродажі Samsung Galaxy F14 5G почнуться 30 березня, але поки що тільки в Індії. Смартфон коштуватиме від $170.