嵌套的正则表达式替换(标记包装)

时间:2011-08-27 20:33:25

标签: php regex nested replace

我需要使用一堆正则表达式进行多个(嵌套)文本替换(例如用标记SPAN包装所有找到的字符串以突出显示),但是......请参阅代码:

<?php

// Sample workaround code:
$html = "hello world";

$regex_array = array(
    '/world/i',
    '/hello world/i'
);

foreach ( $regex_array as $regex ) {
    if ( preg_match_all($regex, $html, $matches) ) {
        foreach ( $matches[0] as $match ) {
            $html = str_replace($match, '<span>' . $match . '</span>', $html);
        }
    }
}

print '<h4>Result:</h4>' 
. htmlentities($html, ENT_QUOTES, 'utf-8');
print '<h4>Expected result:</h4>'
. htmlentities('<span>hello <span>world</span></span>', ENT_QUOTES, 'utf-8');

结果是:

hello <span>world</span>

但预期结果是:

<span>hello <span>world</span></span>

我该怎么做?

是的,我可以更改正则表达式规则的顺序,它可以解决问题,但我真的不能这样做!

1 个答案:

答案 0 :(得分:2)

您应该使用preg_replace_callback代替preg_match_all + str_replace

function handle_matches($matches) {
    return '<span>' . $matches[0] . '</span>';
}
foreach ( $regex_array as $regex ) {
    $html = preg_replace_callback($regex, 'handle_matches', $html);
}

或者使用PHP5.3:

foreach ( $regex_array as $regex ) {
    $html = preg_replace_callback($regex, function($matches) {
        return '<span>' . $matches[0] . '</span>';
    }, $html);
}

对于标签订单问题,没有真正的解决方案是您无法更改订单或修改订单。