preg_replace

Replaces every part of a string that matches a regular expression with a replacement.

Signature
preg_replace(string|array $pattern, string|array $replacement, string|array $subject, int $limit = -1, int &$count = null): string|array|null
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$patternstring|arrayOne pattern, or an array of patterns applied in order.
$replacementstring|arrayThe replacement text, or an array of replacements paired positionally with the patterns. Backreferences are written $1, ${1} or \1.
$subjectstring|arrayThe string, or array of strings, to run the replacement on.
$limitoptionalint= -1Maximum replacements per pattern per subject; -1 means unlimited.
$countoptionalint= nullPassed by reference and filled with the total number of replacements performed.

Return value

string|array|nullAn array if subject is an array, otherwise a string. Returns null if an error occurred.

Errors

Returns null and emits an E_WARNING when a pattern fails to compile or the engine fails at runtime; check preg_last_error() to tell the two apart.

Changelog

  • PHP 7.0The /e (eval) modifier was removed. Use preg_replace_callback() instead.

preg_replace() rewrites every match of a pattern. In the replacement text, $0 is the whole match and $1, $2… are the capture groups; ${1} is the form to use when a digit follows, as in ${1}0.

When to reach for it

Use it for shape changes a literal replace cannot express: collapsing runs of whitespace, reordering the parts of a date, stripping every character outside an allow-list, or turning CamelCase into snake_case. If both sides are fixed strings, str_replace() is several times faster and cannot be broken by a stray metacharacter.

What trips people up

The big one: on error it returns null, and if you assign that back over your variable you have silently destroyed the data — a backtrack-limit failure on one large input turns a whole field into null. Check the return value before assigning. Passing arrays for pattern and replacement applies them in sequence, so the second pattern sees the output of the first, which is a classic source of double replacements. And when the subject is an array the keys are preserved.

Example

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

When to use it

  • Collapse runs of whitespace and newlines into single spaces before storing text
  • Reformat dates from YYYY-MM-DD into DD/MM/YYYY using backreferences
  • Strip everything except letters, digits and hyphens when building a URL slug

Frequently asked questions

What is the difference between preg_replace and str_replace?

str_replace matches fixed substrings, preg_replace matches a regular expression and supports backreferences in the replacement. If you do not need patterns, str_replace is faster and safer.

Why does preg_replace return null?

null means the call failed — either the pattern would not compile (you will also see an E_WARNING) or the engine hit a limit such as the backtrack limit. Call preg_last_error_msg() for the reason.

How do I use a capture group in the replacement string?

Write $1 for the first group, $2 for the second, and $0 for the whole match. Use ${1} when the next character is a digit, so that ${1}0 is not read as group 10.

More examples

Limit and count

With a limit of 2 only the first two x's become y, giving 'y y x x' and a count of 2. A limit of -1 means unlimited, giving 'y y y y' and a count of 4.

Example · php
<?php
$s = 'x x x x';

echo preg_replace('/x/', 'y', $s, 2, $n), "\n";
echo "replaced: $n\n";

echo preg_replace('/x/', 'y', $s, -1, $all), "\n";
echo "replaced: $all\n";

Arrays are applied in sequence

The first line prints 'ccc', not 'bbb': every a becomes b, then every b (including the new ones) becomes c. The second call shows that an array subject returns an array with the same string keys.

Example · php
<?php
// Second pattern runs on the result of the first.
echo preg_replace(['/a/', '/b/'], ['b', 'c'], 'aaa'), "\n";

// Subject arrays keep their keys.
$rows = ['tel' => '555-1234', 'fax' => '555-9876'];
print_r(preg_replace('/\d{4}$/', 'XXXX', $rows));

Building a slug

The first replace turns every run of non-alphanumeric characters into a single hyphen; the second trims the hyphens left at the ends. The output is 'hello-world-php-8-5-release'.

Example · php
<?php
$title = '  Hello, World! -- PHP 8.5 Release  ';

$slug = strtolower(trim($title));
$slug = preg_replace('/[^a-z0-9]+/', '-', $slug);
$slug = preg_replace('/^-+|-+$/', '', $slug);

echo $slug, "\n";

Discussion

  • Be the first to comment on this lesson.