如何识别重复定界符之间的标记?

时间:2018-08-22 00:00:40

标签: php regex preg-replace-callback

我正在尝试解析在两边用@分隔令牌的模板。

示例输入:

  

你好,@ name @!请联系admin@example.com,亲爱的@name @!

所需的输出:

  

你好,彼得!亲爱的彼得,请联系admin@example.com!

天真的尝试找到匹配项并替换:

$content = 'Hello, @name@! Please contact admin@example.com, dear @name@!';

preg_replace_callback(
    '/(@.*@)/U', function ($token) {
        if ('@name@' == $token)  //replace recognized tokens with values
            return 'Peter';

        return $token;  //ignore the rest
    }, $content);

此正则表达式无法正确处理备用@-它匹配第一个@name@@example.com, dear @,但不匹配第二个@name,因为一个{{1} }已经花完了。输出为:

  

你好,彼得!请联系admin@example.com,亲爱的@name @!

为防止花费@,我尝试使用环顾四周:

@

这正确匹配了一对$content = 'Hello, @name@! Please contact admin@example.com, dear @name@!'; preg_replace_callback( '/(?<=@)(.*)(?=@)/U', function ($token) { if ('name' == $token) //replace recognized tokens with values return 'Peter'; return $token; //ignore the rest }, $content); 之间包含的每个子字符串,但不允许我替换定界符本身。输出为:

  

你好,@ Peter @!请联系admin@example.com,亲爱的@Peter @!

如何传递在一对@之间进行回调的所有内容,并替换掉@之间的内容?

令牌不会包含换行符或@

另一个例子

这有点人为,但是为了展示我想做的事情,因为当前的建议依赖于单词边界。

输入

  

狗@猫@驴@斑马

我希望回溯获取@来查看是否应将Cat替换为令牌值,然后接收@Cat@来查看是否要替换Donkey

2 个答案:

答案 0 :(得分:1)

我建议使用:/@\b([^@]+)\b@/

Capture group0 holds:  @name@
Capture group1 holds:  name

答案 1 :(得分:1)

由于定界符可能重叠,因此我不确定可以使用正则表达式来做到这一点。但是,这里有一个递归函数可以完成任务。这段代码并不关心令牌的外观(即不必是字母数字),只要它出现在@个符号之间即可:

function replace_tokens($tokens, $string) {
    $parts = explode('@', $string, 3);
    if (count($parts) < 3) {
        // none or only one '@' so can't be any tokens to replace
        return implode('@', $parts);
    }
    elseif (in_array($parts[1], array_keys($tokens))) {
        // matching token, replace
        return $parts[0] . $tokens[$parts[1]] . replace_tokens($tokens, $parts[2]);
    }
    else {
        // not a matching token, try further along...
        // need to replace the `@` symbols that were removed by explode
        return $parts[0] . '@' . $parts[1] . replace_tokens($tokens, '@' . $parts[2]);
    }
}

$tokens = array('name' => 'John', 'Cat' => 'Goldfish', 'xy zw' => '45');
echo replace_tokens($tokens, "Hello, @name@! Please contact admin@example.com, dear @name@!") . "\n";
echo replace_tokens($tokens, "Dog@Cat@Donkey@Zebra") . "\n";
echo replace_tokens($tokens, "auhdg@xy zw@axy@Cat@") . "\n";
$tokens = array('Donkey' => 'Goldfish');
echo replace_tokens($tokens, "Dog@Cat@Donkey@Zebra") . "\n";

输出:

Hello, John! Please contact admin@example.com, dear John!
DogGoldfishDonkey@Zebra
auhdg45axyGoldfish
Dog@CatGoldfishZebra