Signature
preg_replace(
string|array $pattern,
string|array $replacement,
string|array $subject,
int $limit = -1,
int &$count = null
): string|array|nullPurpose
preg_replace() searches one or more strings for matches of a Perl-compatible regular expression and replaces each match with new text. Use it when the text to find is described by a pattern, such as runs of whitespace, a word followed by digits, or an e-mail-like token. When you only need to replace an exact piece of text, str_replace() or str_ireplace() is simpler and avoids pattern syntax entirely.
Signature
Parameters and defaults
$pattern: a delimited pattern such as'/\s+/', optionally with modifiers after the closing delimiter. It can also be an array of patterns, which are applied one after another.$replacement: the text that replaces each match. It may contain references to captured groups, written as$1or\1; the$nform is preferred.$0or\0is the whole match. Groups are numbered by their opening parenthesis, from left to right. If a literal digit must follow a reference, isolate the reference with braces, as in${1}1.$subject: the string to search, or an array of strings. With an array, every entry is processed and the result is an array. Keys of an associative array are preserved.$limit: the maximum number of replacements for each pattern in each subject string. The default-1means no limit.$count: an optional by-reference variable that receives the total number of replacements made.
Return value and failure cases
The function returns a string when $subject is a string, and an array when $subject is an array. If nothing matches, the subject comes back unchanged. If an error occurs, the return value is null. A pattern that does not compile produces an E_WARNING, and so does the removed e modifier. Always compare against null explicitly when the input might trigger a regex failure, and use preg_last_error() to find out what happened.
Example 1: backreferences and the count
The captured word before the @ is reused in the replacement through $1, and $count reports how many substitutions took place.
$count = 0;
$result = preg_replace('/(\w+)@example\.com/', '$1 at example dot com', 'Mail ana@example.com or bo@example.com', -1, $count);
echo json_encode(['result' => $result, 'count' => $count], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";{"result":"Mail ana at example dot com or bo at example dot com","count":2}
Example 2: collapsing whitespace and using a limit
The first call normalises every run of whitespace. The second stops after two replacements, so the later gap is left untouched.
$text = "alpha beta \t gamma delta";
echo json_encode([
preg_replace('/\s+/', ' ', $text),
preg_replace('/\s+/', '-', $text, 2),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";["alpha beta gamma delta","alpha-beta-gamma delta"]
Example 3: pattern arrays and subject arrays
When both $pattern and $replacement are arrays, the pairs run sequentially. Each pair works on the output of the previous pair, not on the original string. The subject here is an associative array, so its keys survive.
$subjects = ['first' => 'a', 'second' => 'cab'];
$patterns = ['/a/', '/b/', '/c/'];
$replacements = ['b', 'c', 'd'];
echo json_encode(preg_replace($patterns, $replacements, $subjects), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";{"first":"d","second":"ddd"}
The string a becomes b, then c, then d. That chain effect is why swapping two values in a single call does not work. Use an intermediate placeholder if you need a swap.
Edge cases
- The
$limitapplies per pattern and per subject string, not to the whole call. Three patterns with a limit of 1 can produce up to three replacements in one string. - If the replacement array has fewer elements than the pattern array, the extra patterns are replaced with an empty string.
- Array pairs are processed in the order the keys appear, not in numeric index order. If you build arrays with explicit indexes, call
ksort()on both before using them. - A reference such as
\11is ambiguous. Write${1}1when you mean group 1 followed by the digit 1. - Single-quoted PHP strings keep backslashes, so
'\d'reaches the regex engine as\d. In a replacement, a literal backslash or dollar sign may need extra escaping. - Nothing matching is not an error. Check
$count, not the return value, to learn whether anything changed.
Common mistakes
- Forgetting the delimiters, for example passing
'\d+'instead of'/\d+/'. This triggers a warning and anullresult. - Treating the result as always a string. A failed run yields
null, which can silently turn into an empty string when echoed. - Using
preg_replace()for plain literal text, which is slower and invites escaping errors. - Expecting parallel replacement from pattern arrays, when they are applied sequentially.
- Putting user input directly into a pattern without
preg_quote(), so special characters change the meaning of the regex. - Needing logic in the replacement. A static replacement string cannot compute anything, and
preg_replace_callback()is the right tool there.
Related functions
preg_replace_callback()computes each replacement with a function.preg_filter()is similar but returns only subjects where something matched.preg_match()tests for a match and extracts groups.preg_split()splits by a pattern.preg_quote()escapes text for use inside a pattern.preg_last_error()reports the last PCRE error code.str_replace()replaces exact substrings.
Recap
preg_replace() rewrites every match of a regular expression, up to an optional limit, and can report the number of replacements through $count. It accepts strings or arrays for all three main arguments, applies pattern arrays in sequence, preserves array keys, and returns null on failure. Reach for it when the target is a pattern, and choose simpler string functions when it is not.
Tested examples
$count = 0;
$result = preg_replace('/(\w+)@example\.com/', '$1 at example dot com', 'Mail ana@example.com or bo@example.com', -1, $count);
echo json_encode(['result' => $result, 'count' => $count], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";
{"result":"Mail ana at example dot com or bo at example dot com","count":2}
$text = "alpha beta \t gamma delta";
echo json_encode([
preg_replace('/\s+/', ' ', $text),
preg_replace('/\s+/', '-', $text, 2),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";
["alpha beta gamma delta","alpha-beta-gamma delta"]
$subjects = ['first' => 'a', 'second' => 'cab'];
$patterns = ['/a/', '/b/', '/c/'];
$replacements = ['b', 'c', 'd'];
echo json_encode(preg_replace($patterns, $replacements, $subjects), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
echo "\n";
{"first":"d","second":"ddd"}