quotemeta()
Статья о функции PHP quotemeta(), которая экранирует метасимволы в строке для использования в регулярных выражениях.
Функция PHP quotemeta() добавляет обратный слеш перед каждым символом, имеющим специальное значение в регулярном выражении, и возвращает новую «экранированную» строку. Используйте её, когда нужно взять произвольный текст и сопоставить его буквально внутри шаблона, чтобы символы вроде ., * или ( воспринимались как обычный текст, а не операторы регулярных выражений.
На этой странице рассматриваются синтаксис, список экранируемых символов, практический пример, типичная ошибка с разделителями и ситуации, когда лучше воспользоваться preg_quote().
Синтаксис
quotemeta(string $str): stringФункция принимает один аргумент:
$str— входная строка для экранирования.
Она возвращает новую строку с экранированными специальными символами. Исходная строка не изменяется. Если $str — пустая строка, возвращается пустая строка.
Какие символы экранируются
quotemeta() ставит обратный слеш перед каждым из следующих символов:
. \ + * ? [ ^ ] $ ( )Это полный список. Всё, что не входит в этот набор — включая !, ,, =, -, {, } и | — остаётся без изменений. Это частый источник путаницы: quotemeta() не экранирует все «пунктуационные» символы, а только одиннадцать перечисленных выше.
Простой пример
Результат:
Hello\^World!Символ ^ экранируется, поскольку является метасимволом регулярного выражения, тогда как ! остаётся без изменений — он не входит в экранируемый набор.
Более полный пример
Чтобы увидеть полное поведение функции, экранируем строку, содержащую несколько метасимволов:
<?php
$pattern = 'price: $9.99 (per item)*';
echo quotemeta($pattern);
?>Вывод:
price: \$9\.99 \(per item\)\*Обратите внимание: пробел, двоеточие и цифры остались без изменений, а $, ., (, ) и * получили обратный слеш.
Зачем это нужно
Смысл экранирования — сопоставлять введённый пользователем текст буквально. Без экранирования поисковый запрос вроде a.b будет соответствовать axb, a-b и любому другому варианту a + символ + b, потому что . в регулярных выражениях означает «любой символ»:
<?php
$term = 'a.b';
$haystack = 'axb';
// Unescaped: '.' acts as a wildcard and matches 'x'
var_dump((bool) preg_match("/$term/", $haystack));
// Escaped: '.' is treated literally, so it does not match
$escaped = quotemeta($term);
var_dump((bool) preg_match("/$escaped/", $haystack));
?>Вывод:
bool(true)
bool(false)quotemeta() vs preg_quote()
quotemeta() появилась до того, как в PHP появился движок PCRE, и не экранирует все символы, которые PCRE считает специальными — например, {, }, | и /. Кроме того, она не умеет экранировать разделитель шаблона.
Для PCRE-шаблонов (preg_match(), preg_replace() и подобных) почти всегда предпочтительнее использовать preg_quote(), которая экранирует полный набор метасимволов PCRE и принимает необязательный аргумент-разделитель, чтобы экранировать и его тоже:
<?php
$term = 'a/b';
echo preg_quote($term, '/'); // a\/b
?>Используйте quotemeta() только для ограниченных случаев в стиле POSIX, для которых она была создана; для всего, что связано с регулярными выражениями в современном PHP, используйте preg_quote().
Связанные функции
preg_quote()— экранирование строки для использования в PCRE-шаблоне (рекомендуемый вариант).preg_match()— выполнение сопоставления с регулярным выражением.preg_replace()— поиск и замена с использованием регулярного выражения.addslashes()— экранирование кавычек и обратных слешей для строковых литералов, а не регулярных выражений.