preg_quote

Escapes regular expression special characters so a string can be used literally in a pattern.

Signature
preg_quote(string $str, ?string $delimiter = null): string
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$strstringThe input string to escape.
$delimiteroptional?string= nullAn extra character to escape, normally the delimiter you are about to wrap the pattern in, such as '/'.

Return value

stringThe input string with every regex metacharacter (and the delimiter, if given) prefixed by a backslash.

Changelog

  • PHP 7.3.0The # character is now quoted, so patterns built with preg_quote() are safe under the x (extended) modifier.
  • PHP 7.2.0delimiter is nullable.

preg_quote() backslash-escapes every character PCRE treats as special: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : - # and, since PHP 7.3, #. NUL bytes become \000. Everything else, including spaces and /, is left alone.

When to reach for it

Any time part of a pattern comes from outside your source code — a search box, a filename, a configuration value, a database column. Without it, a user typing c++ or ( either breaks your pattern with a compile warning or, worse, turns their input into a working regex against your data. Wrap the dynamic part and leave your own anchors and modifiers outside the call.

What trips people up

/ is not escaped by default because it is not a metacharacter; if you delimit with / you must pass it as the second argument, or a slash in the input ends your pattern early. Never run it on a replacement string for preg_replace() — the escaping rules there are different, and you only need to guard $ and \. And escaping does not make a pattern fast: a quoted 5 KB blob is still a 5 KB pattern.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Build a case-insensitive search pattern from a user-supplied search term
  • Match a literal filename or path fragment that may contain dots and brackets
  • Highlight every occurrence of a keyword in a page of text without breaking on punctuation

Frequently asked questions

Does preg_quote escape the forward slash?

Not by default, because / is not a regex metacharacter. Pass it as the second argument — preg_quote($s, '/') — whenever you build a pattern delimited with slashes.

Should I use preg_quote on the replacement string of preg_replace?

No. Replacement strings have different rules; escaping them with preg_quote leaves visible backslashes in the output. To make a replacement literal, escape only backslashes and dollar signs, or use preg_replace_callback.

Which characters does preg_quote escape?

It escapes . \ + * ? [ ^ ] $ ( ) { } = ! < > | : - and, since PHP 7.3, #. NUL bytes are converted to \000, and the optional delimiter argument is escaped too.

More examples

What happens without it

The first call does not fail — it returns 1. In PCRE2 the second '+' makes the first one possessive, so '/c++/' compiles fine and matches a bare run of c's: $matches[0] is just 'c', and the same pattern would match 'a cat' too. That is the real danger of unescaped input — it silently becomes a different pattern, not necessarily a broken one. The second call returns 1 because preg_quote turned the input into 'c\+\+', which matches the literal text 'c++'. (For input that genuinely fails to compile, use something like '(' or 'c(*'.)

Example · php
<?php
$userInput = 'c++';

// Unescaped: '/c++/' compiles - the second '+' only makes the first
// possessive - so it matches a bare 'c' anywhere, not the literal 'c++'.
preg_match('/' . $userInput . '/', 'a cat', $m);
var_dump($m[0]);   // string(1) "c"

// Escaped: matched literally.
var_dump(preg_match('/' . preg_quote($userInput, '/') . '/', 'c++ is fine'));   // int(1)

// Input that really does break the pattern:
var_dump(@preg_match('/' . '(' . '/', '('));                                   // bool(false)
var_dump(preg_match('/' . preg_quote('(', '/') . '/', '('));                    // int(1)

The slash trap

The first line prints 'wp\-content/uploads': the hyphen IS on preg_quote's list and gets escaped, while the slash is left alone — which is what would terminate a '/...' pattern at the slash. Passing '/' as the delimiter argument produces 'wp\-content\/uploads', which is safe to embed.

Example · php
<?php
$path = 'wp-content/uploads';

echo preg_quote($path), "\n";        // slash left alone
echo preg_quote($path, '/'), "\n";   // slash escaped

var_dump((bool) preg_match('/' . preg_quote($path, '/') . '/', 'in wp-content/uploads/2026'));

Highlighting a search term

Both the dollar sign and the dot in the search term are escaped, so only the literal $9.99 is wrapped and $19.99 is left alone. Note that $0 in the replacement string is deliberately not quoted — preg_quote is for patterns, never for replacements.

Example · php
<?php
$text = 'Prices: $9.99 and $19.99 (incl. VAT)';
$term = '$9.99';

$out = preg_replace(
    '/' . preg_quote($term, '/') . '/',
    '[$0]',
    $text
);

echo $out, "\n";

Discussion

  • Be the first to comment on this lesson.