替换字符串中的嵌套括号对

时间:2013-02-04 15:29:44

标签: php regex recursion replace nested

在PHP中我有一些字符串标签(伪代码):

[TAG_A]              = X
[TAG_B]              = Y
[TAG_X]              = Z

所以当我在字符串中替换这些标签时:

[TAG_A] and [TAG_B] are connected with [TAG_[TAG_A]]

它应输出:

X and Y are connected with Z

问题出在嵌套标签上。它需要是递归的,首先替换内部标记。所有可能的标签(及其值)都存储在一个大型数组中。

我想要一个替换方法,不仅使用强力来替换所有标记,而是使用标记数组上的foreach,但实际上只搜索字符串中的[] - 对,以及然后在tags-array中查找值。

我认为正则表达式不是正确的方法,但是做这样的事情最有效的方法是什么?

1 个答案:

答案 0 :(得分:1)

替换字符串中的标签,然后检查过程后是否出现新标签。再次运行代码,直到没有更多标签要替换。

$string = '[TAG_A] and [TAG_B] are connected with [TAG_[TAG_A]]';
$search = array(
    '[TAG_A]'   => 'X',
    '[TAG_B]'   => 'Y',
    '[TAG_X]'   => 'Z'
);
$continue = true;
while ($continue) {
    foreach ($search as $find => $replace) {
        $string = str_replace($find, $replace, $string);
    }
    $continue = false;
    foreach ($search as $find => $replace) {
        if (strpos($string, $find) !== false) {
            $continue = true;
            break;
        }
    }
}
echo $string; // prints "X and Y are connected with Z"

正则表达式解决方案:

$string = '[TAG_A] and [TAG_B] are connected with [TAG_[TAG_A]]';
$search = array(
    'TAG_A' => 'X',
    'TAG_B' => 'Y',
    'TAG_X' => 'Z'
);
while(preg_match_all('/\[([^\[\]]*?)\]/e', $string, $matches)) {
    $string = preg_replace('/\[([^\[\]]*?)\]/e', '$search["$1"]', $string);
}
echo $string;