5

我刚刚在http://regexcrossword.com/上做了有趣的正则表达式填字游戏- 发现我不明白量化组的含义,例如 (.)+ 或 (.)*

让我试试http://ole.michelsen.dk/tools/regex.html,它提供了 JavaScript 和 PHP 正则表达式引擎:

要匹配的字符串是“Trololo!” (不带引号)。(如果打开“全局匹配”改变了某些东西,它会作为初始版本添加,即 JS',因为它在 PHP 模式下没有改变任何东西。)

JS,  (.)+ => 0: Trololo! 1: ! 
JS', (.)+ => 0: Trololo! 
PHP, (.)+ => 0: Trololo! 0: ! 
JS,  (.)* => 0: Trololo! 1: ! 
JS', (.)* => 0: Trololo! 
PHP, (.)* => 0: Trololo! 1: 0: ! 1: 
JS,  (.){5} => 0: Trolo 1: o 
JS', (.){5} => 0: Trolo 
PHP, (.){5} => 0: Trolo 0: o 
JS,  (.){4} => 0: Trol 1: l 
JS', (.){4} => 0: Trol 1: olo! 
PHP, (.){4} => 0: Trol 1: olo! 0: l 1: ! 

有什么规范的答案吗?这是什么语义?

4

1 回答 1

3

输出没有正确标记,仅此而已。

首先,应该怎么办?如果您重复一个组,每个新实例都会覆盖最后一次捕获。如果根本不使用该组,它将返回一个空字符串或类似undefinedJS 中的内容(这取决于风格)。关于这个问题, regular-expressions.info上有一篇很好的文章。

现在我们如何得到你的结果?让我们从 JavaScript 开始。

所有标记的示例JS(非全局示例)都符合上述描述。它们匹配所需数量的字符0并捕获1. 所以我们可以忽略这些。

全球的怎么了?这里的输出被错误地解释了。当您将全局标志与String.match()函数一起使用时,您不会再获得所有捕获的数组 - 而只会获得所有匹配的数组(0每个匹配的组)。因此,在 的情况下+*并且{5}只有一个匹配项,您只能得到一个结果。由于{4}目标字符串中有足够的空间容纳两个匹配项,因此结果数组包含两个元素。要使用全局标志获取所有捕获,您需要编写一个循环并RegExp.exec()改为使用(它一次为您提供一个匹配,但它的所有捕获)。

PHP 是怎么回事?似乎它正在 using preg_match_all,无论如何它都是全局的,这就是为什么 usingg没有效果。+给出了您再次期望的结果。也是如此{5}

另外两个是什么情况?在这里,输出被错误地解释了。默认情况下,preg_match_all给出一个二维数组,其中第一个索引对应于组,第二个对应于匹配项。在您的输出中,它被反过来解释。因此,当有多个匹配时,第一对01是两个找到的匹配的完整匹配。第二对01您在这两场比赛中捕获的。

因此,对于*,您首先将完整的字符串作为匹配项,并将最后一个字符作为捕获(标记为 的两件事0),这是正确的。然后,由于*允许零宽度匹配,您会在字符串末尾获得另一个(空)匹配,以及一个空捕获。不过,我不确定为什么相应的JS'示例不包含额外的空字符串,因为String.match会做同样的事情。

而对于{4},您只需获得两个匹配项 (Trololo!),就像在 JavaScript 案例中分别捕获l和一样!,这也很好。

于 2013-07-29T21:21:31.223 回答