Извлечение данных с помощью функции preg_match()

Глобальный объект RegExp

Этот глобальный объект служит для боступа к результатам поиска с использованием регулярных выражений.
Этот объект создается самим интерпритатором и доступен всегда. Формат доступа к его свойствам:

RegExp.свойство

Свойства

Свойство Описание
$номер подвыражения Возвращает одно из последних найденых подвыражений (зависит от номера).
Номер может быть 1-9, т.к.интерпретатор хранит в этом свойстве только девять последних найденых подвыражений,
для доступа к остальным используется массив, возвращенный методами match или exec
index Возвращает позицию в строке найденой подстроки
input|&_ Возвращает строку, где производится поиск
lastIndex Задает позицию начала поиска в строке
lastMatch|$& Возвращает последнюю найденую подстроку
lastParent|$+ Возвращает последнюю найденую группу символов, если в регулярном выражении использовались подвыражения
leftContext|$’ Возвращает строку, составленую из всех символов от начала строки до последней найденой подстроки, не включая ее
rightContext|$’ Возвращает строку, составленую из всех символов от последней найденой подстроки, не включая ее, до конца исходной строки

Ленивая и жадная квантификация

Жадность — это стремление интерпретатора захватить максимально длинную строку, которая соответствует шаблону. Например, у нас есть строка:

Если мы хотим получить выражение в первых скобках, то попробуем задать вот такую маску: /\(.*\)/. Результат будет таким:

Обуздать жадность интерпретатора можно двумя способами:
1. В маске запретить двигаться дальше одной закрывающей скобки — /\(*\)/.
2. Воспользоваться ленивым квантификатором, добавив знак вопроса после звездочки — /\(.*?\)/.

После чего результат будет таким как мы и хотели:

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

Жадный Ленивый
* *?
+ +?
{n,} {n,}?

К сожалению, алгоритм поиск последовательностей в регулярных выражениях очень громоздкий — он имеет рекурсивный вид.
Чтобы избежать ненужных итераций обычно используют ревнивые квантификаторы (сверхжадные). Но JavaScript, почему-то, их не поддерживает.

Разбор URL

Данный скрипт разбивает интернет адрес на несколько составных частей. В регелярном выражении использовалось
несколько подвыражений, которые сохраняются интерпритатором следующим образом: сначала сохраняется внешнее
выражение, а затем внутренее. После регулярного выражения следует строка (result=re.exec(str);), которая
начинает разбивание адреса, а далее проверяется правильность адреса и, в случае положительного результата,
происходит присваивание переменным соответствующих частей адреса.

Использование g для глобального последовательного поиска

В браузере мы увидим такой результат:

Кош — начинается с 0-го символа
Дальше поиск начнется с 3-го символа

кор — начинается с 8-го символа
Дальше поиск начнется с 11-го символа

кот — начинается с 22-го символа
Дальше поиск начнется с 25-го символа

Маску поиска и её параметры можно также указывать через конструктор объекта RegExp:

Разбиваем числа на троичные (тысячные) группы:

$1 — эта переменная содержит значение первого соответствия (первые «запоминающие» скобки в регулярном выражении)

Еще про регулярные выражения:

  • Регулярные выражения в PHP
  • примеры регулярных выражений
  • regexr.com — Сервис проверки регулярных выражений
  • pagecolumn.com — Сервис проверки регулярных выражений
  • uiregex.com — создание регулярных выражений

Условная компиляция в JavaScript

Регулярные выражения в разных языках программирования

Здесь я приведу примеры использования регулярных выражений в различных языках программирования

Заранее говорю, я не буду заострять внимание на синтаксисе языка программирования, так как это уже не касается данной темы. C#

C#

Здесь мы создаем строку с текстом, который хотим проверить, создаем объект класса Regex и в конструктор пишем нашу регулярку (как я и говорил, я не буду заострять внимание на том, что такое объект класса и конструктор). Потом создаем объект класса MatchCollection и от объекта regex вызываем метод Matches и в параметры передаем нашу строку

В результате все сопоставления будут добавляться в коллекцию matches.

Java

Здесь похожая ситуация. Создаем объект класса Pattern и записываем нашу строку. CASE_INSENSITIVE означает, что он не привязан к регистру (то есть нет разницы между заглавными и строчными символами). Создаем объект класса Matcher и пишем туда регулярку.

JavaScript

Здесь тоже все просто. Вы создаете объект regex и пишете туда регулярку. И затем просто создаете объект matches, который будет являться коллекцией и вызываете метод exec и в параметры передаете строку.

Операторы для работы с регулярными выражениями в Javascript

exec(regexp) — находит все совпадения (вхождения в шаблон «регулярки») в строке. Возвращает массив (при совпадении) и обновляет свойство regexp-а, или null — если ничего не найдено,.
С модификатором g — при каждом вызове этой функции, она будет возвращать следующее совпадение после предыдущего найденного — это реализовано с помощью ведения индекса смещения последнего поиска.

match(regexp) — найти часть строки по шаблону. Если указан модификатор g, то функция match() возвращает массив всех совпадений или null (а не пустой массив). Без модификатора g эта функция работает как exec();

test(regexp) — функция проверяет строку на соответствие шаблону. Возвращает true — если есть совпадение, и false — если совпадения нет.

replace(regexp, mix) — метод возвращает строку изменную в соответствии с шаблоном (регуляррным выражением). Первый параметр regexp также может содержать строку, а не регулярное выражение. Без модификатора g — метод в строке заменяет только первое вхождение; с модификатором g — происходит глобальная замена, т.е. меняются все вхождения в данной строке. mix — шаблон замены, может принитать значения строки, шаблона замены, функции (имя функции).

Стоит подробнее остановиться на методе replace(), его второй параметр mix нужно описать более детально.

Если второй параметр mix содержит строку, то мы можем использовать следующие спецсимволы:

  • $$ — вставить $;
  • $& — совпавшая подстрока;
  • $` — часть строки перед совпавшей подстроки;
  • $’ — часть строки после совпавшей подстроки;
  • $n ($nn) — значение n-ой запоминающей скобки (если первый аргумент — объект RegExp);

Если второй параметр mix содержит функцию, то она будет вызванна при каждом совпадении. Значением для замены будет результат работы функции, т.е. return »;

Примеры таких функции:

Следующий вызов replace возвратит XXzzzz — XX , zzzz.

Как видите, тут две скобки в регулярном выражении, и потому в функции два параметра p1, p2.
Если бы были три скобки, то в функцию пришлось бы добавить параметр p3.

Следующая функция заменяет слова типа borderTop на border-top:

function styleHyphenFormat(propertyName)
{
  function upperToHyphenLower(match)
  {
    return '-' + match.toLowerCase();
  }
  return propertyName.replace(//, upperToHyphenLower);
}

Таким блоком кода я разбираю javascript вхождения в html:

Класс RegExp

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

RegExp(Регулярное выражение, Флаги)

Он принимает только один обязательный пареметр — это «Регулярное выражение», которое заключается в кавычки.
Параметр «флаги» представляет собой дополнительные условия поиска и может принимать значения:

  • g — задается глобальный поиск, если этот флаг установлен, то выражение возвратит все подходящие слова.
  • i — игнорирование регистра символов
  • m — многострочный поиск

Для работы с регулярными варажениями используются три метода класса String:

  • match — выполняет поиск в строке, используя регулярное выражение, переданное в качестве параметра
    и возвращает массив с результатами поиска. Если ничего не найдено, возвращается null.
  • replace — выполняет поиск и замену в строке, используя регулярные выражения, и возвращает полученную строку.
  • search — выполняет поик в строке, используя регулярное выражение, переданное в качестве параметра,
    и возвращает позицию первой подстроки, совпадающей с регулярным выражением.

Свойства

Свойство Описание
lastIndex Задает позицию начала поиска в строке
sourse Возвращает строку регулярного выражения (только чтение)
global Определяет наличие флага g и возвращает соответсявенно true или false
ignoreCase Определяет наличие флага i и возвращает соответсявенно true или false
multilane Определяет наличие флага m и возвращает соответсявенно true или false

Методы

Метод Описание
compile (Регулярное выражение g,i,m) Компилирует регулярное выражение во внутренний формат для ускорения работы, может использоваться для изменения регулярного выражения
exec(строка) Аналогичен методу match класса String, но строка, где нужно произвести поиск, передается в качестве параметра
test(строка) Аналогичен методу search класса String, возвращает true или false в зависимости о результатов поиска

Пример

Здесь этот участок скрипта производит поиск текста «www» в строке, которая была присвоена переменной «str» без учета регистра,
а метод match возвращает массив result, содержащий результаты поиска.

PHP regex character classes

We can combine characters into character classes with the square brackets.
A character class matches any character that is specified in the brackets.

characterclass.php

<?php

$words = ;

$pattern = "/it/";

foreach ($words as $word) {

    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match the pattern\n";
    }
}

We define a character set with two characters.

$pattern = "/it/";

This is our pattern. The is the character class. Note
that we work only with one character at a time. We either consider
f, or s, but not both.

$ php characterclass.php 
sit matches the pattern
MIT does not match the pattern
fit matches the pattern
fat does not match the pattern
lot does not match the pattern

This is the outcome of the script.

We can also use shorthand metacharacters for character classes.
The stands for alphanumeric characters,
for digit, and whitespace characters.

shorthand.php

<?php

$words = ;
$pattern = "/\w{6}/";

foreach ($words as $word) {

    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match the pattern\n";
    }
}

In the above script, we test for words consisting of alphanumeric characters.
The stands for six alphanumeric characters. Only the word
does not match, because it contains non-alphanumeric characters.

php> echo preg_match("#{3}#", "ABC");
1

The pattern stands for three characters that are
not in the class a-z. The «ABC» characters match the condition.

php> print_r(preg_grep("#\d{2,4}#", ));
Array
(
     => 32
     => 234
     => 2345
)

In the above example, we have a pattern that matches 2, 3, and 4 digits.

Функции регулярных выражений

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

Функция Определение
preg_match() Эта функция ищет конкретный образец в некоторой строке. Он возвращает 1 (true), если шаблон существует, и 0 (false) в противном случае.
preg_match_all() Эта функция ищет все вхождения шаблона в строке. Она возвращает количество найденных совпадений с шаблоном в строке, или 0 — если вхождений нет. Функция удобна для поиска и замены.
ereg_replace() Эта функция ищет определенный шаблон строки и возвращает новую строку, в которой совпадающие шаблоны были заменены другой строкой.
eregi_replace() Функция ведет себя как ereg_replace() при условии, что поиск шаблона не чувствителен к регистру.
preg_replace() Эта функция ведет себя как функция ereg_replace() при условии, что регулярные выражения могут использоваться как в шаблоне так и в строках замены.
preg_split() Функция ведет себя как функция PHP split(). Он разбивает строку на регулярные выражения в качестве параметров.
preg_grep() Эта функция ищет все элементы, которые соответствуют шаблону регулярного выражения, и возвращает выходной массив.
preg_quote() Эта функция принимает строку и кавычки перед каждым символом, который соответствует регулярному выражению.
ereg() Эта функция ищет строку, заданную шаблоном, и возвращает TRUE, если она найдена, иначе возвращает FALSE.
eregi() Эта функция ведет себя как функция ereg() при условии, что поиск не чувствителен к регистру.

Примечание:

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

Функция preg_match()

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

Пример. Поиск подстроки «php» в строке без учета регистра:

Попробуй сам

Результат выполнения кода:

Вхождение найдено.

В примере выше символ «i» после закрывающего ограничителя шаблона означает регистронезависимый поиск, поэтому вхождение будет найдено.

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

Функция preg_match_all()

Функция выполняет глобальный поиск шаблона в строке.

В примере регулярное выражение используется для подсчета числа вхождений «ain» в строку без учета регистра:

Попробуй сам

Результат выполнения кода:

3

Функция preg_replace()

Функция выполняет поиск и замену по регулярному выражению.

В следующем функция выполняет поиск в строке совпадений с шаблоном pattern и заменяет их на replacement:

Повторения (квантификаторы)

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

Повторения символов или комбинаций описываются с помощью квантификаторов (метасимволов, которые задают количественные отношения). Есть два типа квантификаторов: общие (задаются с помощью фигурных скобок ) и сокращенные (сокращения наиболее распространенных квантификаторов). Фигурные скобки задают число повторений предыдущего символа (в этом случае выражение ищет от 1 до 7 идущих подряд букв «x»).

Квантификатор Описанте
a+ Один и более раз a
a* Ноль и более раз a
a? Одна a или пусто
a{3} 3 раза a
a{3,5} От 3 до 5 раз a
a{3,} 3 и более раз a

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

Перечень обычных и спецсимволов

При экранировании обычного символа ничего особенного не случится, и он все равно будет обозначать себя сам. Исключениями являются цифры, которые станут карманами. Также исключением будет модификатор ‘X’: когда он установлен, экранировка обычных символов вызывает ошибку.

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

  • Что является спецсимволами: $ ^ . * + ? \ {} [] () |
  • А что не является: @ : , ‘ » ; — _ = < > % # ~ `& ! /
  • Также спецсимволами будут выбранные ограничители.

Вдобавок к этому, # будет спецсимволом в случае наличия модификатора ‘x’ (речь идет именно про маленький ‘x’, разрешающий комментарии).

Метасимволы

В приведенных выше примерах использовались простые шаблоны. Метасимволы позволяют выполнять более сложные сопоставления шаблонов PHP regexp, такие как проверка адреса электронной почты. Рассмотрим часто используемые метасимволы.

Метасимвол Описание Пример
. Обозначает любой единичный символ, кроме символа новой строки. /./ — все, что содержит один символ.
^ Обозначает начало строки, не включая символ /. /^PH/ — любая строка, которая начинается с PH.
$ Обозначает шаблон в конце строки. /com$/ — guru99.com,yahoo.com и т.д.
* Обозначает любое количество символов, ноль или больше. /com*/ — computer, communication и т.д.
+ Требуется вхождение перед метасимволом символа (ов) хотя бы один раз. /yah+oo/ — yahoo.
Символ экранирования. /yahoo+.com/ — воспринимает точку, как дословное значение.
Класс символов. // — abc.
a-z Обозначает строчные буквы. /a-z/ — cool, happy и т.д.
A-Z Обозначает заглавные буквы. /A-Z/ — WHAT, HOW, WHY и т.д.
0-9 Обозначает любые цифры от 0 до 9. /0-4/ — 0,1,2,3,4.

Теперь рассмотрим сложный PHP regexp пример, в котором проверяется валидность адреса электронной почты:

<?php
$my_email = "name @ company . com"
if (preg_match("/^+@+.{2,5}$/", $my_email)) {
echo "$my_email is a valid email address";
}
else
{
  echo "$my_email is NOT a valid email address";
}
?>

Результат: адрес электронной почты name@company.com является валидным.

Опережающие и ретроспективные проверки — (?=) and (?

d(?=r) соответствует d, только если после этого следует r, но r не будет входить в соответствие выражения -> тест(?<=r)d соответствует d, только если перед этим есть r, но r не будет входить в соответствие выражения -> тест

Вы можете использовать оператор отрицания !

d(?!r) соответствует d, только если после этого нет r, но r не будет входить в соответствие выражения -> тест(?<!r)d соответствует d, только если перед этим нет r, но r не будет входить в соответствие выражения -> тест

Заключение

Как вы могли убедиться, области применения регулярных выражений разнообразны. Я уверен, что вы сталкивались с похожими задачами в своей работе (хотя бы с одной из них), например такими:

  • Валидация данных (например, правильно ли заполнена строка time)
  • Сбор данных (особенно веб-скрапинг, поиск страниц, содержащих определённый набор слов в определённом порядке)
  • Обработка данных (преобразование сырых данных в нужный формат)
  • Парсинг (например, достать все GET параметры из URL или текст внутри скобок)
  • Замена строк (даже во время написания кода в IDE, можно, например преобразовать Java или C# класс в соответствующий JSON объект, заменить “;” на “,”, изменить размер букв, избегать объявление типа и т.д.)
  • Подсветка синтаксиса, переименование файла, анализ пакетов и многие другие задачи, где нужно работать со строками (где данные не должны быть текстовыми).

Перевод статьи Jonny Fox: Regex tutorial — A quick cheatsheet by examples

Основы основ

Для начала нужно понять что в Regex есть специальные символы (например символ начала строки — ), если вы хотите просто найти данный символ, то нужно ввести обратный слеш перед символом для того, чтобы символ не работал как команда.

Для того чтобы найти текст, нужно собственно просто ввести этот текст:

Якори

— символ который обозначает начало строки

— символ который обозначает конец строки

Найдем строки которые начинаются с The Beginning:

Найдем строки, которые заканчиваются на The End:

Найдем строки, которые начинаются и заканчиваются на The Beginning and The End:

Найдем пустые строки:

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

— символ, который указывает на то, что выражение до него должно встретиться 0 или 1 раз

— символ, который указывает на то, что выражение до него должно встретиться один или больше раз

— символ, который указывает на то, что выражение до него должно встретиться 0 или неопределённое количество раз

— скобки с одним аргументом указывают сколько раз выражение до них должно встретиться

— скобки с двумя аргументами указывают на то, от скольки до скольки раз выражение до них должно встретиться

— скобки объединяют какое-то предложение в выражение. Обычно используется в связке с квантификаторами

Давайте попробуем найти текст, в котором будут искаться все слова, содержащие ext или ex:

Давайте попробуем найти текст, в котором слова будут содержать ext или e:

Найти все размеры одежды (XL, XXL, XXXL):

Найти все слова, у которых есть неограниченное число символов c, после которых идёт haracter:

Найти выражение, в котором слово word повторяется от одного до неограниченного количества раз:

Найти выражение, в котором выражение ch повторяется от 3 до неограниченного количества раз:

Выражение «или»

— символ, который обозначает оператор «или»

— выражение в квадратных скобках ставит или между каждым подвыражением

Найти все слова, в которых есть буквы a,e,c,h,p:

Найти все выражения в которых есть ch или pa:

Escape-последовательности

— отмечает один символ, который является цифрой (digit)\

— отмечает символ, который не является цифрой

— отмечает любой символ (число или букву (или подчёркивание)) (word)

— отмечает любой пробельный символ (space character)

— отмечает любой символ (один)

Выражения в квадратных скобках

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

— один символ от 0 до 9

— любой символ от a до z

— любой символ от A до Z

— любой символ кроме a — z

Найти все выражения, в которых есть английские буквы в нижнем регистре или цифры:

Флаги

Флаги — символы (набор символов), которые отвечают за то, каким именно образом будет происходить поиск.

Форма условия поиска в Regex выглядит вот так:

— флаг, который будет отмечать все выражения, которые соответствуют условиям поиска (по умолчанию поиск возвращает только первое выражение, которое подходит по условию) (global)

— флаг, который заставляет искать выражения вне зависимости от региста (case insensitive)

Ещё один реальный пример

Практически на любом современном сайте все адреса вида: https://php.zone/post/892

Эти адреса нужно обрабатывать прямо в коде, и понимать, что показать пользователю. Это называется «роутинг» — специальные правила, по которым нужно преобразовать адрес, по которому пришел пользователь, в конкретное действие на стороне сервера. То есть получив адрес вида /post/892 ваш код должен понять, что:

  1. это post, то есть статья
  2. идентификатор этой статьи — 892

Дальше он ищет статью в базе данных с таким идентификатором и возвращает её пользователю.

Вопрос: как это сделать? Да проще простого! Создать список шаблонов для всех страниц сайта. И когда прилетает запрос на /post/+ — то искать статью с каким-то идентификатором. Да, да, вы уже догадались, сделать это можно с помощью регулярок. И это будет вашим домашним заданием.

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

В PHP есть поддержка 2 типов записи РВ — POSIX и Perl. POSIX (Portable Operating System Interface) представляет собой интерфейс переносной операционной системы и стандарт для интерфейсов приложений. Сейчас мы рассмотрим РВ POSIX и Perl-совместимые РВ.

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

ereg()

bool ereg(string pattern, string string )

Эта функция осуществляет поиск соответствия РВ в строке string, который задан в шаблоне pattern. В случае наличия соответствий шаблона с подвыражениями их сохранят в массиве соответствий regs. В $regs имеется копия строки string, а в $regs находится подстрока, которая начинается с первой левой скобки. Подстрока со второй левой скобки хранится в $regs и т. д.

Рассмотрим код, который из формата YYYY-MM-DD преобразовывает формат даты в  DD.MM.YYYY.

<? $date = "2015-03-21";
if (ereg ("({4})-({1,2})-({1,2})", $date, $regs)){
        echo "$regs.$regs.$regs";
    }
    else{
        echo "Неверный формат даты: $date";
    }
?>

ereg_replace()

string ereg_replace(string pattern, string replacement, string string)

Данная функция меняет шаблон pattern, который был обнаружен в строке string, на строку replacement. При наличии соответствия происходит осуществление модифицированной строки.

Будьте внимательны: указание числа как типа, который отличен от строкового, является ошибкой — число должно всегда указываться как строка.

<? 
$number = "1952";
$str = "Он родился в пятьдесят втором.";
echo("до замены:$str");
$str = ereg_replace("пятьдесят втором", $number, $str);
echo("<br> после замены: $str");
?>

Результат:

до замены: Он родился в пятьдесят втором.после замены: Он родился в 1952.

eregi()

bool eregi (string pattern, string string)

Данная функция аналогична ereg. Отличие состоит в том, что регистр игнорируется.

eregi_replace()

string eregi_replace (string pattern, string replacement, string string)

Отличие данной функции от ereg_replace состоит в том, что она не является чувствительной к регистру.

split()

array split (string pattern, string string )

Данная функция проводит возвращение массива строк из подстрок строк string, которые были образованы в соответствии с РВ pattern в ходе разделения строки string на подстроки. При указании параметра limit (он не является обязательным) возвращаемый массив будет иметь до limit элементов, причем в последнем имеется неразделенная часть строки.

Данная функция окажет пользу при разделении доменных имен, дат и проч. Например:

<? 
$url = "www.softtime.ru";
$array = split ("\.", $url); 
foreach($array as $index => $val) {
    echo("$index -> $val <br />");  
}?>

В результате будет следующее:

0 -> www 1 -> softtime 2 -> ru

Это же можно осуществить и с датой:

<?
$date = "10-12-2003"
$array = split ("-", $date);
foreach($array as $index => $val){
    echo("$index -> $val <br />");
}
?>

В результате мы получим:

0 -> 10 1 -> 12 2 -> 2015

spliti()

array spliti (string pattern, string string )

2 Практический раздел. Ссылки

Перед тем, как использовать регулярные выражения, стоит посмотреть в документацию по вашему языку программирования и используемой библиотеке, так как диалекты обладают особенностями. Например в Perl и некоторых версиях php можно описывать рекурсивные регулярные выражения, которые не поддерживаются большинством других реализаций; механизмом флагов отличается JavaScript и так далее. Незначительными отличиями могут обладать даже различные версии одной и той же библиотеки.

Отличаются регулярные выражения не только синтаксисом, но и реализацией. Регулярные выражения — это «не просто так». Строка, задающее выражение, преобразуется в автомат, от реализации которого зависит эффективность. Масштаб проблемы хорошо иллюстрирует график зависимости времени выполнения поиска от длины строки и реализации:

Картинка взята из статьи «Поиск с помощью регулярных выражений может быть простым и быстрым«. В ней можно прочитать про различные реализации выражений, а также о том, как написать выражение так, чтобы оно работало быстрее. Кстати, так как выражение преобразуется в автомат, то зачастую его удобно визуализировать — для этого есть специальные сервисы, например. Для последнего выражения статьи будет построен такой автомат:

Примеры использования регулярных выражений:

  • для валидации вводимых в поля данных: QValidator примеры использования. Ряд библиотек построения графического пользовательского интерфейса позволяют закреплять к полям ввода валидаторы, которые не позволяет ввести в формы некорректные данные. По приведенной выше ссылке можно найти валидацию номера банковской карты и номера телефона с помощью регулярных выражений библиотеки Qt. Аналогичные механизмы есть в других языках, например в Java для этого используется пакет ;
  • для парсинга сайтов: Парсер сайта на Qt, использование QRegExp. В примере с сайта-галереи выбираются и скачиваются картинки заданных категорий;
  • для валидации данных, передаваемых в формате JSON ряд библиотек позволяет задавать схему. При этом для строковых полей могут быть заданы регулярные выражения. В качестве упражнения можно попробовать составить выражение для пароля — проверить что строка содержит символы в разном регистре и цифры.

В сообществе Программирование и алгоритмы можно посмотреть дополнительную литературу по теме. Книгу Гойвертса и Левитана рекомендую посмотреть особенно, так как в ней по-полочкам разобраны десятки примеров, причем с учетом специфики реализации регулярных выражений в конкретных языках программирования.

Буквы, цифры, символы

В регулярных выражениях существуют два вида символов: обозначающие сами себя и символы, которые называют командами (спецсимволы).

Цифры и буквы обозначают сами себя, зато точка — спецсимвол, обозначающий «любой символ». Смотрим примеры:

По сути, в коде выше не существует разницы между функциями preg_replace и str_replace – функционируют они одинаково, разница заключается лишь в ограничителях.

В следующем примере можно увидеть, как использовался спецсимвол «точка» — такое уже нельзя сделать с помощью str_replace:

Раз точка — любой символ, то под регулярку подпадут все подстроки, причем по следующему шаблону: буква ‘x’, потом любой символ, потом снова ‘x’. Первые четыре подстроки попали под данный шаблон (xax xsx x&x x-x), поэтому они заменились на ‘!’. Последняя подстрока (xaax) не подпала по той причине, что внутри (между буквами ‘x’) находится не один, а два символа.

Раз точка — любой символ, а в регулярке мы видим 2 точки подряд, то под регулярку подпадут все подстроки по следующему шаблону: буква ‘x’, потом 2 любых символа, потом снова ‘x’. Первая подстрока не подпадет, т. к. она содержит лишь один символ между буквами ‘x’, в то время как последняя подстрока (xabx) шаблону соответствует.

Что тут важно запомнить: цифры и буквы обозначают сами себя, точка же заменяет любой символ. Также важно следующее: для функции preg_match точка на деле обозначает любой символ за исключением перевода строки

Дабы точка обозначала и его, необходим модификатор s.

PHP regex dot metacharacter

The (dot) metacharacter stands for any single character in the text.

single.php

<?php

$words = ;
$pattern = "/.even/";

foreach ($words as $word) {

    if (preg_match($pattern, $word)) {
        echo "$word matches the pattern\n";
    } else {
        echo "$word does not match the pattern\n";
    }
}

In the array, we have five words.

$pattern = "/.even/";

Here we define the search pattern. The pattern is a string. The regular expression
is placed within delimiters. The delimiters are mandatory.
In our case, we use forward slashes as delimiters. Note that we
can use different delimiters if we want. The dot character stands for any single character.

if (preg_match($pattern, $word)) {
    echo "$word matches the pattern\n";
} else {
    echo "$word does not match the pattern\n";
}

We test all five words if they match with the pattern.

$ php single.php 
Seven matches the pattern
even does not match the pattern
Maven does not match the pattern
Amen does not match the pattern
Leven matches the pattern

The Seven and Leven words match our search pattern.

PHP regex exact word match

In the following examples we show how to look for exact word matches.

php> echo preg_match("/mother/", "mother");
1
php> echo preg_match("/mother/", "motherboard");
1
php> echo preg_match("/mother/", "motherland");
1

The pattern fits the words mother, motherboard and motherland.
Say, we want to look just for exact word matches. We will use the aforementioned
anchor and characters.

php> echo preg_match("/^mother$/", "motherland");
0
php> echo preg_match("/^mother$/", "Who is your mother?");
0
php> echo preg_match("/^mother$/", "mother");
1

Using the anchor characters, we get an exact word match for a pattern.

Маски

Маски это очень крутая вещь в регулярках, которая используется повсеместно. Благодаря им можно не только проверить строку на соответствие шаблону, но и выделить из неё некоторые подстроки и использовать их отдельно!

Пример задачи: нужно из строки Меняем автора статьи 123 c «Иван» на «Пётр» извлечь идентификатор статьи и имена авторов.

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

Нагляднее всего это можно увидеть на примере:

Видите, справа у нас появились дополнительные совпадения? В PHP мы можем сделать из этого отдельные переменные!

Делается это проще простого:

Результат:

Первым в $matches всегда будет полное совпадение строки шаблону. А далее — значения, попавшие в маски.

Соответственно, нам остаётся лишь определить переменные под всё это дело:

Вот и всё!

Однако, если ничего не совпало, в $matches будет пустой массив, и в реальном коде это всегда нужно учитывать и добавлять дополнительные проверки.

А ещё маске можно дать имя прямо в шаблоне, вот так:

В коде будет выглядеть вот так:

Теперь $matches примет вид:

И мы можем получить id статьи вот так:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector