quotemeta
Escapes a small set of regular-expression metacharacters in a string with backslashes.
quotemeta(string $string): string- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The input string. The function is binary-safe. |
Return value
stringThe string with a backslash inserted before each of the characters . \\ + * ? [ ^ ] ( $ )
quotemeta inserts a backslash before each occurrence of these eleven characters and nothing else:
. \ + * ? [ ^ ] ( $ )
That list dates back to old POSIX regular expressions. It is not sufficient for PCRE, which is what preg_match, preg_replace and every other preg_* function use.
Use preg_quote instead
PCRE also treats {, }, |, -, /, # and as special in some contexts, and quotemeta escapes none of them. A user-supplied search term containing {2} or | will therefore still be interpreted as a pattern, which at best returns wrong results and at worst is a regular-expression injection. preg_quote escapes the full PCRE set and takes a second argument for your delimiter, which quotemeta cannot do at all.
So when is it right?
Realistically: when you are working with a legacy POSIX-style matcher, when you are reproducing the behaviour of another system that uses this exact character set, or when you need those eleven characters escaped for some non-regex format. For new code that builds a PCRE pattern from untrusted input, reach for preg_quote every time.
The function is binary-safe and returns an empty string for empty input; older documentation claiming it returns false no longer applies.
Example
When to use it
- Escape the twelve legacy metacharacters when reproducing another system's POSIX-style quoting rules.
- Neutralise . * ? and brackets in a string being written into a non-PCRE matcher or config format.
- Compare its output against preg_quote when auditing old code for regex injection.
Frequently asked questions
What is the difference between quotemeta and preg_quote?
quotemeta escapes only eleven legacy POSIX metacharacters, while preg_quote escapes the full PCRE set including { } | - # and an optional delimiter. Use preg_quote for anything passed to a preg_* function.
Which characters does quotemeta escape?
Exactly these: . \ + * ? [ ^ ] ( $ ) — a backslash is inserted before each one. Everything else, including braces and pipes, is left untouched.
Does quotemeta return false for an empty string?
No. On PHP 8 it returns an empty string. The old documentation note about false describes behaviour that no longer applies.
More examples
Side by side with preg_quote
For this particular string the two functions agree — dots and parentheses are in both escape sets — and the match returns 1. That agreement is exactly what lulls people into using quotemeta generally; the next example shows where it breaks.
<?php
$needle = 'v1.2 (beta)';
echo 'quotemeta: ', quotemeta($needle), PHP_EOL;
echo 'preg_quote: ', preg_quote($needle, '/'), PHP_EOL;
var_dump(preg_match('/' . quotemeta($needle) . '/', 'release v1.2 (beta) shipped'));Where quotemeta is not enough
The first call returns 1 — wrong. quotemeta left the braces alone, so `a{2}` was still a quantifier and matched the literal text "aa". preg_quote escapes the braces, so it correctly fails on "aa" (0) and matches the literal string "a{2}" (1). Any user input containing braces or a pipe behaves this way.
<?php
$pattern = 'a{2}';
var_dump(preg_match('/' . quotemeta($pattern) . '/', 'aa'));
var_dump(preg_match('/' . preg_quote($pattern, '/') . '/', 'aa'));
var_dump(preg_match('/' . preg_quote($pattern, '/') . '/', 'a{2}'));
Discussion