Preg quote: примеры (PHP)
preg_quote(string $string, ?string $delimiter = null): stringБазовая информация о preg_quote
Функция preg_quote() в языке PHP применяется для экранирования специальных символов, имеющих значение в регулярных выражениях. Её использование актуально, когда необходимо обрабатывать строки с неизвестным содержанием и включать их в шаблон регулярного выражения как простой литерал, без интерпретации метасимволов.
Основная задача функции — подготовка произвольной строки для безопасного использования внутри шаблона PCRE. Это предотвращает случайное толкование символов, таких как ., *, +, [, ] и других, как элементов регулярного выражения.
Функция принимает два аргумента:
- string (
$str) — обязательный. Обрабатываемая строка, символы в которой требуется экранировать. - string|null (
$delimiter) — необязательный. Символ, который используется как разделитель в регулярном выражении (например,/,#,~). Этот символ также будет экранирован. Начиная с PHP 8.0.0, аргумент может принимать значениеnull.
Возвращаемое значение — строка, в которой все специальные символы регулярных выражений предварены обратным слешем (\).
Простые примеры использования
Функция экранирует метасимволы: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : - #.
<?php
$string = 'Пример. строки+с *символами?';
$result = preg_quote($string);
echo $result;
?>Пример\. строки\+с \*символами\?
При указании разделителя он также экранируется в выходной строке.
<?php
$string = 'Путь /usr/local/bin';
$result = preg_quote($string, '/');
echo $result;
?>Путь \/usr\/local\/bin
Символ \\ (обратный слеш) также экранируется, так как он является escape-символом в регулярных выражениях.
<?php
$string = 'Цена C:\Windows';
$result = preg_quote($string);
echo $result;
?>Цена C:\\Windows
Похожие функции в PHP
Прямых аналогов для экранирования символов PCRE в PHP не существует. Однако есть функции для работы с регулярными выражениями, которые могут применяться в схожих сценариях.
Функция quotemeta() экранирует специальные символы, но для POSIX-регулярных выражений (ereg). Она добавляет обратный слеш перед символами: . \\ + * ? [ ^ ] ( $ ). Функция не экранирует символы {, }, =, !, <, >, |, :, -, # и не поддерживает параметр разделителя. preg_quote() является более предпочтительной для работы с PCRE.
Для сложной обработки строк перед использованием в регулярных выражениях иногда применяют preg_replace_callback() или ручное экранирование через str_replace(). Однако это менее эффективно и более подвержено ошибкам.
Типичные ошибки
Если в регулярном выражении используется разделитель, а при вызове preg_quote() он не указан, это приведет к синтаксической ошибке в шаблоне.
<?php
$search = '/путь/к/файлу';
$pattern = '/' . preg_quote($search) . '/'; // Ошибка, не экранирован '/'
echo $pattern;
?>/\/путь\/к\/файлу/
Проблема: в строке $search содержится символ /, который является разделителем в итоговом шаблоне //. После экранирования без указания разделителя, слеши в строке экранируются, но сам разделитель шаблона не добавляется. Ошибки не будет, но лучше явно указать разделитель.
До PHP 8 передача массива вызывала предупреждение и возвращала null. В PHP 8 такое вызовет TypeError.
<?php
// PHP 7.x
$result = preg_quote(['test']);
var_dump($result);
?>NULL (и предупреждение)
Изменения в PHP 8
В PHP 8.0.0 аргумент $delimiter стал необязательным и может принимать значение null. В предыдущих версиях PHP этот аргумент был обязательным.
<?php
// Работает в PHP 8, вызовет ошибку в PHP 7
$result = preg_quote('test.string');
?>Кроме того, в PHP 8 ужесточена типизация: передача нескалярных значений (кроме строк) вызывает исключение TypeError.
Расширенные примеры
Функция позволяет безопасно вставлять пользовательский ввод в сложные шаблоны.
<?php
$user_input = 'file.[txt|pdf]';
$delimiter = '#';
$pattern = $delimiter . '^' . preg_quote($user_input, $delimiter) . '$' . $delimiter . 'i';
echo "Шаблон: " . $pattern . "\n";
// Проверка
$test_string = 'FILE.[TXT|PDF]';
if (preg_match($pattern, $test_string)) {
echo "Строка соответствует шаблону.";
}
?>Шаблон: #^file\.\[txt\|pdf\]$#i Строка соответствует шаблону.
При построении шаблона с вариантами выбора, каждую часть необходимо экранировать.
<?php
$keywords = ['test.php', 'index.html', 'file.tar.gz'];
$escaped_keywords = array_map('preg_quote', $keywords);
$pattern = '/(' . implode('|', $escaped_keywords) . ')/';
echo "Шаблон: " . $pattern . "\n";
$subject = 'Ищем test.php в папке';
if (preg_match($pattern, $subject, $matches)) {
echo "Найдено: " . $matches[0];
}
?>Шаблон: /(test\.php|index\.html|file\.tar\.gz)/ Найдено: test.php
Использование тильды как разделителя, когда в строке присутствуют слеши.
<?php
$path = '/home/user/file.txt';
$pattern = '~^' . preg_quote($path, '~') . '$~';
echo $pattern;
?>~^/home/user/file\.txt$~
Функция также экранирует символ нулевого байта (\000) как \\000, что может быть важно при работе с бинарными данными.
<?php
$string = "test\000string";
$result = preg_quote($string);
echo bin2hex($result); // Для наглядности вывода
?>746573745c303030737472696e67 (что соответствует "test\\000string")
Альтернативы в других языках
Функция re.escape() из модуля re выполняет аналогичную задачу. Она экранирует все не-алфавитно-цифровые символы, кроме _. В Python нет параметра для экранирования разделителя.
import re
string = 'Пример. строки+с *символами?'
result = re.escape(string)
print(result)
Пример\.\ строки\+с\ \*символами\?
Preg quote в Javascript
В JavaScript нет нативной функции для экранирования строк регулярных выражений. Обычно используют пользовательские реализации или библиотеки.
function preg_quote(str, delimiter = '/') {
return (str + '')
.replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\\\' + delimiter + '-]', 'g'), '\\$&');
}
console.log(preg_quote('Цена C:\\Windows', '/'));
Цена C:\\Windows
В MySQL при использовании оператора REGEXP экранирование специальных символов не предусмотрено на уровне функции. Необходимо экранировать обратными слешами вручную или с помощью функции REPLACE().
-- Ручное экранирование для поиска точки
SELECT 'test.string' REGEXP 'test\.string';
1