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