preg_replace with multiple patterns replacements at once

孤街醉人 提交于 2019-12-05 02:50:39

问题


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?


回答1:


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.




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!