2017-04-26 16 views
2

所有的话,我有以下形式获得具有不特定的前缀组

$string = "This is {test} for [a]{test2} for {test3}."; 

我想不是由方括号前缀的大括号的字符串。因此,在上面的字符串中,我想获得{test}{test3},但不是[a]{test2}

我在回答https://stackoverflow.com/a/977294/2311074中发现,这可能是负面的预测。所以我试了

$regex  = '/(?:(?!\[[^\}]+\])\{[^\}]+\})/'; 
    echo preg_match_all($regex, $string, $matches) . '<br>'; 
    print_r($matches); 

但这仍然给我所有三个大括号。

阵列([0] =>数组([0] => {测试} [1] => {TEST2} [2] => {TEST3}) )

为什么这不起作用?

+0

@WiktorStribiżew感谢您的详细解答。我正在追赶这个主题的负面看法。一旦我理解了,我会立即回复/提出你的回答。 – Adam

+0

请问什么是不清楚的 - 我将在网上几个小时。 –

回答

1

您正则表达式失败的原因是,它的任何{(接着用1 +非}秒,然后一})如果不启动排除模式内模式的序列相匹配,一个[,1+字符除了},然后是](并且总是如此,因此,您将得到所有{...}子字符串)。

使用(*SKIP)(*FAIL) technique

\[[^]]*]\{[^}]+}(*SKIP)(*F)|\{[^\}]+} 

regex demo

详细

  • \[[^]]*]\{[^}]+}(*SKIP)(*F) - 匹配
    • \[ - 一个[
    • [^]]* - 比0+字符等]
    • ]\{ - ]{
    • [^}]+ - 1+字符比]
    • }其他 - 文字}
    • (*SKIP)(*F) - PCRE动词到目前为止丢弃匹配的文本,并迫使引擎去寻找从当前位置的下一场比赛(好像比赛发生)
  • | - 或
  • \{[^\}]+}
    • \{ - 文字} - 一个{
    • [^\}]+ - 比}
    • }其他1+字符。

PHP demo

$string = "This is {test} for [a]{test2} for {test3}."; 
$regex  = '/\[[^]]*]\{[^}]+}(*SKIP)(*F)|\{[^}]+}/'; 
echo preg_match_all($regex, $string, $matches) . "\n"; 
print_r($matches[0]); 

输出:

2 
Array 
(
    [0] => {test} 
    [1] => {test3} 
) 
+0

谢谢。我只是意识到我的rexgex有一个错误,我实际上想使用'/(?<!\ [[^ \}] + \])\ {[^ \}] + \} /''但是这个不工作,因为**“lookbehind断言必须是固定长度”** http://stackoverflow.com/questions/3796436/whats-the-technical-reason-for-lookbehind-assertion-must-be-fixed-长度在-R。所以在这里使用跳过失败方法是有道理的,而不是倒退。谢谢! – Adam

+0

很高兴我能帮到你。 '(* SKIP)(* FAIL)'是唯一正确的方式否定PCRE中的某些东西,而无需进行假设,否则无法访问负向无限宽度的后视图。 –

2

如果您确信打开花括号只会用方括号对(平衡)开头,然后负面后顾之心将会做到这一点:

(?<!]){[^}]*} 

Live demo

+0

非常好的提示,谢谢:)!是否有必要转义']和'}'? – Adam

相关问题