Regex Lookahead问题和改进

时间:2014-11-06 18:46:51

标签: php regex pcre

现在我使用下面的正则表达式跳过{% ... %}

之间的所有内容
(\\|\.|\*|\/|\-|\)|\+|\$|\||\[|\]|\(|\^|\?|\!|\~|\`)(?![^{%]*?%})

然而,这有时不能正常工作,因为当我有文字时:

"This is test. ! {%.?{1}.%} .  and it doesn't work"

它会中断并且它也匹配{i} {}}区域中我不想要的点。 {% %}{打破了它。 否定前瞻应该查找}字符串,而不是单个字符{%{

应跳过}之间的所有内容。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

通过你的正则表达式,我看到你犯了一些错误,我会指出。

1 - (?![^{%]*?%})用简单的词来表示 除了{%..%} 之外的所有内容。 您使用了字符集[^{%],这意味着{ %而不是{%。所以它说的是:之前的一个字符后面跟着{%除了零个或多个字符,结尾到%}

换句话说,您可以像(?!%})一样编写,这就是为什么这些特殊字符匹配的原因除了.之前的%}

"This is test. ! {%.?{1}.%} .  and it doesn't work"
                        ^

2 - 因此,您不应仅检查{%,而应检查两者。但是,当我看到您的正则表达式时,您只能检查%(?![^%]*?%})。但如果您的输入字符串如下所示,它将失败:

"This is test.%} ! {%.%?{1}.%} .  and it doesn't work"
                     ^

也会捕获指向dot

3 - 一个很好的解决方案是使用 Tempered Dot ,我从rexegg.com借用了它的名称约定:(?!(?:(?!{%).)*?%})

这个(?:(?!{%).)*?[^{%]的替代,并且在内部做了一个负向前瞻,它断言当前位置后面的内容不是字符串{%

4 - 我不喜欢(\\|\.|\*|\/|\-|\)|\+|\$|\||\[|\]|\(|\^|\?|\!|\~),必须将其替换为更易读和更简单的内容:([\/.*)($.+|^?!\[\]-])

5 - 它不保证嵌套或非平衡分隔符的正确匹配。

最终解决方案(Live demo):

([\/.*)($.+|^?!`\[\]-])(?!(?:(?!{%).)*?%})