I have few substitutions to apply on my $subject but I don't want to allow the output from old substitutions #(1 .. i-1) to be a match for the current substitution #i.
$subject1 = preg_replace($pat0, $rep0, $subject0);
$subject2 = preg_replace($pat1, $rep1, $subject1);
$subject3 = preg_replace($pat2, $rep2, $subject2);
I tried using one preg_replace with arrays for patterns and replacement hoping that it make it at once; but it turned out to be not more than calling the simple preg_replace successively (with some optimization of course)
After I read about preg_replace_callback, I guess it is not a solution.
Any help?
Use a callback, you can detect which pattern matched by using capturing groups, like (?:(patternt1)|(pattern2)|(etc)
, only the matching patterns capturing group(s) will be defined.
The only problem with that is that your current capturing groups would be shifted. To fix (read workaround) that you could use named groups. (A branch reset (?|(foo)|(bar))
would work (if supported in your version), but then you'd have to detect which pattern has matched using some other way.)
Example
function replace_callback($matches){
if(isset($matches["m1"])){
return "foo";
}
if(isset($matches["m2"])){
return "bar";
}
if(isset($matches["m3"])){
return "baz";
}
return "something is wrong ;)";
}
$re = "/(?|(?:regex1)(?<m1>)|(?:reg(\\s*)ex|2)(?<m2>)|(?:(back refs) work as intended \\1)(?<m3>))/";
$rep_string = preg_replace_callback($re, "replace_callback", $string);
Not tested (don't have PHP here), but something like this could work.
It seems to me that preg_replace_callback
is the most direct solution. You just specify the alternate patterns with the |
operators and inside the callback you code an if
or switch
. Seems the right way to me. Why did you discard it?
An alternative solution is to make a temporary replace to a special string. Say:
// first pass
$subject = preg_replace($pat0, 'XXX_MYPATTERN0_ZZZ', $subject);
$subject = preg_replace($pat1, 'XXX_MYPATTERN1_ZZZ', $subject);
$subject = preg_replace($pat2, 'XXX_MYPATTERN2_ZZZ', $subject);
// second pass
$subject = preg_replace("XXX_MYPATTERN0_ZZZ",$rep0 , $subject);
$subject = preg_replace("XXX_MYPATTERN1_ZZZ",$rep1 , $subject);
$subject = preg_replace("XXX_MYPATTERN2_ZZZ",$rep2 , $subject);
This is very ugly, does not adapt well to dynamic replacements, and it's not foolproof, but for some "run once" script it might be acceptable.
来源:https://stackoverflow.com/questions/6565379/preg-replace-with-multiple-patterns-replacements-at-once