Регулярные выражения в php (часть 1)

В php есть два типа регулярных выражений

  • PCRE
  • POSIX совместимые

последние уже давно объявлены как устаревшие, о чем нам гласит официальный справочник функций на сайте php

Устаревшая функция регулярных выражений в php

 

Что такое регулярные выражения

Это шаблон под который должна попасть строка. Формат шаблона можно представить так :

<разделитель> <шаблон> <разделитель> [<модификаторы>]

Разделителем здесь могут быть разные символы :

/ | @ # ~ () {} [] <> + %

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

пример

here will be a table

Регулярные выражения применяются повсеместно, доступны во многих языках программирования.

Метасимволы

Метасимволов существуют два типа:

  • те , которые используются внутри квадратных скобок
  • метасимволы использующие за квадратными скобками

 

. точка

что соответствует любому одиночному символу ,  кроме перевода строки

примеры

here will be a table

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

+ плюс

означает минимум один максимум неограниченно, например:

here will be a table

? знак вопроса

квантификатор означает либо есть совпадение либо нет, 0 или 1

here will be a table

* звездочка

от 0 символов до бесконечности

примеры

here will be a table

{ } количественный квантификатор

колличественным квантификатором мы кол-во того или иного символа

{m}- точное количество символов

{m,n}- от m до n символов

{,n} — максимум, минимальное значение не ограничено

{m,} — минимальное число, максимум неограничен

Здесь важно чтобы первое число не превышало второе.

например:
here will be a table
Как можно было заметить, аналоги символы * + ? можно записать количественными квантификаторами:
* {0, } — от 0 до неограниченно
+ {1, } — от 1 до неограниченно
? {0, 1} — от 0 до 1
Задача 1 Комментарии
Необходимо в следующем тексте найти все комментарии вида /* */ и /** */
code /* comment */
next code /* comment */
next code /* comment */

next code...
/*
comment 
*/


/**
 * Gets the application start timestamp.
 */
defined('YII_BEGIN_TIME') or define('YII_BEGIN_TIME', microtime(true));
/**
 * This constant defines the framework installation directory.
 */
defined('YII2_PATH') or define('YII2_PATH', __DIR__);

/**
 * @var array class map used by the Yii autoloading mechanism.
 * The array keys are the class names (without leading backslashes), and the array values
 * are the corresponding class file paths (or [path aliases](guide:concept-aliases)). This property mainly affects
 * how [[autoload()]] works.
 * @see autoload()
 */
 public static $classMap = [];
 /**
 * @var \yii\console\Application|\yii\web\Application the application instance
 */
 public static $app;


Решение будет таким  @\/\*.*?\*\/@gus.

Сперва нужно экранировать слеши \/ и \/ так как комментарий начинается и заканчивается этим символом. Тоже самое делаем с символом *.

Далее идут символы  .*? , что означает любой символ, может быть может не быть. После разделителя идут буквы g — значит глобальный поиск в строке, u — означает обрабатывать строки как UTF-8 последовательности и s — означает что символ точка в шаблоне соответствует всем символам включая переводы строк. Таким образом получается рекурсивный поиск по строке. В результате можно конструировать любые рекурсивные вызовы.

Что бы нам тестировать результаты в php для проверки на соответствие регулярному выражению используется функция preg_match ( )

int preg_match (string $pattern , string $subject , array $matches)

где,

$pattern — шаблон по которому искать

$subject — строка где искать

$matches — массив, символы которые попали под регулярное выражение

функция может вернуть три значения:

1 — если совпадение найдено

0 — совпадении нет

false — произошла ошибка

Например:

$reg = preg_match("/./",'String', $match); // 1 совпадение найдено

var_dump($match); // [S]
// Протестируем на примере
// Возьмем значения которые нужно проверить по регулярное выражение /[0-9]{2}/
// Что означает две любые цифры в любом месте строки
$examples = ['0023', '7634','test', 'rt44'];

$result = [];
foreach ($examples as $key => $example) {
    $reg = preg_match("/[0-9]{2}/",$example, $match);
    if (isset($match[0])) {
        $result[$key] = $match[0];
    }
}
var_dump($result); // [0 => '00', 1 => '76', 3 => '44']

// Обратите внимание что значение с ключом 2 - test, не попало в итоговый результат

Если нужен глобальный поиск совпадений в строке используется функция preg_match_all (шаблон, входная строка)

// Например возьмен нашу первую задачу про комментарии
$str = <<<EOD
code /* comment */
next code /* comment */
next code /* comment */

next code...
/*
comment 
*/
/**
 * Gets the application start timestamp.
 */
defined('YII_BEGIN_TIME') or define('YII_BEGIN_TIME', microtime(true));
/**
 * This constant defines the framework installation directory.
 */
defined('YII2_PATH') or define('YII2_PATH', __DIR__);
/**
 * @var array class map used by the Yii autoloading mechanism.
 * The array keys are the class names (without leading backslashes), and the array values
 * are the corresponding class file paths (or [path aliases](guide:concept-aliases)). This property mainly affects
 * how [[autoload()]] works.
 * @see autoload()
 */
 public static \$classMap = [];
 /**
 * @var \yii\console\Application|\yii\web\Application the application instance
 */
 public static \$app;
EOD;

$reg = preg_match_all("@\/\*.*?\*\/@us",$str, $match); // В результате в массиве match будут вырезанные комментарии из текста

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

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

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