正则表达式,带有preg_match_all的模式中的反向引用问题

时间:2011-05-18 20:09:15

标签: php regex preg-match-all backreference

我想知道这里的反向引用有什么问题:

preg_match_all('/__\((\'|")([^\1]+)\1/', "__('match this') . 'not this'", $matches);

期望匹配__('')之间的字符串,但实际上它返回:

match this') . 'not this

任何想法?

4 个答案:

答案 0 :(得分:6)

您不能在字符类中使用反向引用,因为字符类只匹配一个字符,而反向引用可能匹配任意数量的字符,或者没有。或者没有。

你要做的事情需要消极的前瞻,而不是否定的角色类:

preg_match_all('/__\(([\'"])(?:(?!\1).)+\1\)/',
    "__('match this') . 'not this'", $matches);

我还将您的更改 - \'|" - 更改为字符类 - [\'"] - 因为它效率更高,并且我从外部括号中删除它们以使它们与字面括号匹配。< / p>


编辑:我想我需要扩展这个&#34;更高效&#34;备注。我用example Friedl来证明这一点并在RegexBuddy中进行了测试。

应用于目标文字abababdedfg
^[a-g]+$在三个步骤后报告成功,而 ^(?:a|b|c|d|e|f|g)+$需要55步。

成功匹配的那个。当我在abababdedfz上尝试时, ^[a-g]+$在21个步骤后报告失败;
^(?:a|b|c|d|e|f|g)+$需要99步。

在这种特殊情况下,对性能的影响是微不足道的,甚至不值得一提。我只是说,每当你发现自己在一个字符类和一个两个匹配相同的事物的交替之间做出选择时,你几乎总是应该选择角色类。只是一个经验法则。

答案 1 :(得分:2)

我很惊讶它没有给你一个不平衡的括号错误信息。

 /
   __
   (
       (\'|")
       ([^\1]+)
       \1
 /

[^\1]不会获取捕获缓冲区1的内容并将其放入字符
中 类。它与所有不是'1'的字符相同。

试试这个:

/__\(('|").*?\1\).*/

你可以添加一个内部捕捉括号来捕捉引号之间的什么:
/__\(('|")(.*?)\1\).*/

编辑:如果不允许使用内部分隔符,请使用Qtax正则表达式 因为('|").*?\1即使不贪婪,仍将匹配所有尾随锚。在这种情况下__('all'this'will"match'),最好使用('[^']*'|"[^"]*)

答案 2 :(得分:1)

您可以使用以下内容: /__\(("[^"]+"|'[^']+')\)/

答案 3 :(得分:0)

让你的正则表达不成熟:

preg_match_all('/__((\'|")([^\1]+)\1/U', "__('match this') . 'not this'", $matches)