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

我正在尝试解析两边都用@分隔标记的模板.

输入示例:

Hello, @name@! Please contact admin@example.com, dear @name@!

期望的输出

Hello, Peter! Please contact admin@example.com, dear Peter!

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

$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,因为之前已经花费了@.输出是:

Hello, Peter! Please contact admin@example.com, dear @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);

这正确匹配了一对@s之间包含的每个子字符串,但它不允许我自己替换分隔符.输出是:

Hello, @Peter@! Please contact admin@example.com, dear @Peter@!

如何在一对@s之间传递回调任何东西并替换它取代@s?

令牌不包括换行符或@.

一个例子

这有点人为,但要显示我想要做什么,因为当前的建议依赖于字边界.

用于输入

Dog@Cat@Donkey@Zebra

我希望calback让Cat看看是否应该用令牌值替换@ Cat @然后接收Donkey以查看是否要替换@ Donkey @.

解决方法:

由于可能重叠的分隔符,我不确定这可以用正则表达式来完成.但是这里有一个递归函数可以完成这项工作.这段代码不关心令牌是什么样的(即它不必是字母数字),只要它出现在@符号之间:

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

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...