2

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

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

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

match this') . 'not this

有任何想法吗?

4

4 回答 4

6

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

你想要做的事情需要一个否定的前瞻,而不是一个否定的字符类:

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

我还将您的替换 - \'|"- 更改为字符类 - [\'"]- 因为它更有效,并且我转义了外括号以使它们与文字括号匹配。


编辑:我想我需要扩展那个“更有效”的评论。我拿了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 步。

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

于 2011-05-18T21:14:24.680 回答
2

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

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

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

试试这个:

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

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

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

于 2011-05-18T20:34:32.183 回答
1

你可以使用类似的东西: /__\(("[^"]+"|'[^']+')\)/

于 2011-05-18T20:31:09.353 回答
-1

使您的正则表达式不贪婪:

preg_match_all('/__((\'|")([^\1]+)\1/U', "__('match this') . 'not this'", $matches)
于 2011-05-18T20:16:39.127 回答