Php 如何识别重复分隔符之间的标记?

Php 如何识别重复分隔符之间的标记?,php,regex,preg-replace-callback,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 (

我正在尝试解析模板,其中标记由两侧的
@
分隔

输入示例:

你好,@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,亲爱的
,并且无法匹配第二个
@name
,因为之前已经使用了一个
@
。输出为:

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

为了防止花费
@
,我尝试使用lookarounds:

$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);
$content='你好,@name@!请联系admin@example.com,亲爱的@name!';
preg_replace_回调(

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

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

由于分隔符可能重叠,我不确定是否可以使用正则表达式完成此操作。但是,这里有一个递归函数可以完成此操作。此代码不关心标记的外观(即,它不必是字母数字),只要它出现在
@
符号之间:

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";

如果您知道变量名,那么用字符串替换
@name@
而不是查找任何
@…
?而不是对
\w+
进行过于宽泛的
*
匹配,并使用回溯在这之前不断言任何字母,不是更容易吗。@在实际代码中,我运行了一个数据库查询,以查找标记是否已被删除已定义。@Džuris请检查,如果它是您需要的,我将发布。如果您真的想匹配
@
之间的任何字符,也可能是。这很不错,但如果可能的话,我希望避免强制的单词边界。回调应该只接收任何连续两个
@
之间的字符。
Hello, John! Please contact admin@example.com, dear John!
DogGoldfishDonkey@Zebra
auhdg45axyGoldfish
Dog@CatGoldfishZebra