preg_replace with multiple patterns replacements at once

巧了我就是萌 提交于 2019-12-03 20:18:16

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.

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