Skip to content

Instantly share code, notes, and snippets.

@BastienClement
Last active January 16, 2016 16:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BastienClement/61f001071bb8e640a917 to your computer and use it in GitHub Desktop.
Save BastienClement/61f001071bb8e640a917 to your computer and use it in GitHub Desktop.
Smarter preg_replace with support for callback functions and the removed /e modifier.
<?php
function preg_replace_safe($search, $replace, $subject, $evaluator = NULL) {
if (is_null($evaluator)) {
// A custom evaluator
// function($c) { return eval($c); }
// is required if the replacement code uses the $this reference.
$evaluator = function($code) { return eval($code); };
}
if (is_array($subject)) {
return array_map(function($subject) use ($search, $replace) {
return preg_replace_safe($search, $replace, $subject);
}, $subject);
} else {
if (is_array($search) && is_array($replace)) {
$replacements = array_map(function($a, $b) { return [$a, $b]; }, $search, $replace);
} else if(is_array($search)) {
$replacements = array_map(function($a) use($replace) { return [$a, $replace]; }, $search);
} else {
$replacements = [[$search, $replace]];
}
foreach ($replacements as $replacement) {
list ($s, $r) = $replacement;
if (is_callable($r)) {
$subject = preg_replace_callback($s, $r, $subject);
} else {
$stripped = preg_replace('/^(.)(.*\\1[a-z]*)e([a-z]*)$/si', "$1$2$3", $s);
if ($stripped != $s) {
$subject = preg_replace_callback($stripped, function($matches) use ($r, $evaluator) {
$code = preg_replace_callback('/\\$(?|\{(\\d+)\}|(\\d+))/', function($m) use ($matches) {
return addslashes($matches[(int) $m[1]]);
}, $r);
return $evaluator('return ' . $code . ';');
}, $subject);
} else {
$subject = preg_replace($s, $r, $subject);
}
}
}
return $subject;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment