除了2个连续花括号({)之外,还有什么是正则表达式?
示例字符串:
{{some text}} string I want {{another set {{and inner}} }}
我只想获得string i want
。
使用堆栈来做这些事情已经超出了我的想法,但我想知道是否可以使用正则表达式来完成。
我正在使用PHP的PCRE
提前致谢
答案 0 :(得分:6)
使用前瞻断言(?!{{|}})
来验证外部集合中没有嵌套的大括号。
{{((?!{{|}}).)*}}
<?php
$string = '{{lot {{of}} characters}}';
for (;;)
{
var_dump($string);
$replacement = preg_replace('/{{((?!{{|}}).)*}}/', '', $string);
if ($string == $replacement)
break;
$string = $replacement;
}
string(25) "{{lot {{of}} characters}}"
string(19) "{{lot characters}}"
string(0) ""
它似乎也能合理地处理各种边缘情况:
# Unbalanced braces.
string(23) "{{lot {{of}} characters"
string(17) "{{lot characters"
string(23) "lot {{of}} characters}}"
string(17) "lot characters}}"
# Multiple sets of braces.
string(25) "{{lot }}of{{ characters}}"
string(2) "of"
# Lone curlies.
string(41) "{{lot {{of {single curly} }} characters}}"
string(19) "{{lot characters}}"
string(0) ""
答案 1 :(得分:2)
如果你需要做一些更复杂的内容,比如处理内容或变量,那么你可以使用递归正则表达式,利用(?R)运算符。
$data = "{{abcde{{fg{{hi}}jk}}lm}}";
$regexp = "#\{\{((?:[^(\{\{)(\}\})]+|(?R))+)\}\}#";
$count = 0;
function revMatch($matches) {
global $regexp, $count;
if (is_array($matches)) {
// Match detected, process for nested components
$subData = preg_replace_callback($regexp, 'revMatch', $matches[1]);
} else {
// No match, leave text alone
$subData = $matches;
}
// This numbers each match, to demonstrate call order
return "(" . $count++ . ":<" . $subData . ">)";
}
echo preg_replace_callback($regexp, 'revMatch', $data);
这会将{{abcde{{fg{{hi}}jk}}lm}}
转换为(2:<abcde(1:<fg(0:<hi>)jk>)lm>)
关于正则表达式的一些解释:#\{\{((?:[^(\{\{)(\}\})]+|(?R))+)\}\}#
正面和背面的双括号与任何目标组件匹配,大括号的内容是两个定义选项中的一个或多个:
没有双括号的字符串[^(\{\{)(\}\})]+
重复整个正则表达式。 (?:)
括号是非捕获组。
NB。 #s
是模式分隔符,我认为额外的斜杠会进一步降低可读性。