如何识别重复分隔符之间的标记?
How to recognize tokens between repeated delimiters?
我正在尝试解析两侧由 @
分隔标记的模板。
示例输入:
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, dear @
而无法匹配第二个 @name
,因为 @
之前已经用完了。输出为:
Hello, Peter! Please contact admin@example.com, dear @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);
这正确匹配了一对 @
之间包含的每个子字符串,但它不允许我自己替换分隔符。输出为:
Hello, @Peter@! Please contact admin@example.com, dear @Peter@!
如何将一对 @
之间的任何内容传递给回调并替换它以替换 @
?
令牌将不包括换行符或 @
。
另一个例子
这有点做作,但为了展示我想做的事情,因为当前的建议依赖于单词边界。
输入
Dog@Cat@Donkey@Zebra
我希望回调获取 Cat
以查看 @Cat@
是否应替换为令牌值,然后接收 Donkey
以查看 @Donkey@
是否应为已替换。
我建议使用:/@\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";
输出:
Hello, John! Please contact admin@example.com, dear John!
DogGoldfishDonkey@Zebra
auhdg45axyGoldfish
Dog@CatGoldfishZebra
我正在尝试解析两侧由 @
分隔标记的模板。
示例输入:
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, dear @
而无法匹配第二个 @name
,因为 @
之前已经用完了。输出为:
Hello, Peter! Please contact admin@example.com, dear @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);
这正确匹配了一对 @
之间包含的每个子字符串,但它不允许我自己替换分隔符。输出为:
Hello, @Peter@! Please contact admin@example.com, dear @Peter@!
如何将一对 @
之间的任何内容传递给回调并替换它以替换 @
?
令牌将不包括换行符或 @
。
另一个例子
这有点做作,但为了展示我想做的事情,因为当前的建议依赖于单词边界。
输入
Dog@Cat@Donkey@Zebra
我希望回调获取 Cat
以查看 @Cat@
是否应替换为令牌值,然后接收 Donkey
以查看 @Donkey@
是否应为已替换。
我建议使用:/@\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";
输出:
Hello, John! Please contact admin@example.com, dear John!
DogGoldfishDonkey@Zebra
auhdg45axyGoldfish
Dog@CatGoldfishZebra