我刚刚在 http://regexcrossword.com/ 做了有趣的正则表达式填字游戏- 发现我不明白量化组的含义,例如(.)+ 或 (.)*
让我试试http://ole.michelsen.dk/tools/regex.html ,它提供了 JavaScript 和 PHP 正则表达式引擎:
要匹配的字符串是“Trololo!” (不带引号)。 (如果打开“全局匹配”改变了什么,它被添加为 primed 版本,即 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: !
有什么规范的回答这是什么语义吗?
最佳答案
输出没有正确标记,仅此而已。
首先,应该发生什么?如果您重复一个组,每个新实例都会覆盖最后一次捕获。如果根本不使用该组,它将返回一个空字符串或类似 JS 中的 undefined
的内容(这取决于风格)。 regular-expressions.info 上有一篇很好的文章关于这件事。
现在我们如何获得您的结果?让我们从 JavaScript 开始吧。
所有标记为 JS
的示例(非全局示例)都符合上述描述。它们匹配 0
中所需数量的字符并捕获 1
中的最后一个字符。所以我们可以忽略这些。
全局的有什么用?这里的输出被错误地解释了。当您将全局标志与 String.match()
函数一起使用时,您不会再获得所有捕获的数组 - 但只会获得所有匹配项的数组(组 0
每场比赛)。因此,在 +
、*
和 {5}
只有一个匹配项的情况下,您只能得到一个结果。对于 {4}
,目标字符串中有足够的空间容纳两个匹配项,因此生成的数组包含两个元素。要使用全局标志获取所有捕获,您需要编写一个循环并改用 RegExp.exec()
(它一次为您提供一个匹配项,但它的所有捕获)。
PHP 有什么用?看起来它正在使用 preg_match_all
,无论如何它是全局的,这就是为什么使用 g
没有效果。 +
再次给出您期望的结果。 {5}
也是如此。
另外两个呢?在这里,输出被错误地解释了。默认情况下,preg_match_all
给出一个二维数组,其中第一个索引对应组,第二个索引对应匹配项。在您的输出中,它以相反的方式解释。因此,当存在多个匹配项时,第一对 0
和 1
是两个找到的匹配项的完整匹配项。第二对 0
和 1
是您在这两场比赛中捕获的内容。
因此对于 *
,您首先获得完整的字符串作为匹配项,最后一个字符作为捕获(标记为 0
的两个东西),这是正确的。然后,由于 *
允许零宽度匹配,您会在字符串末尾得到另一个(空)匹配,以及一个空捕获。不过,我不确定为什么相应的 JS'
示例不包含额外的空字符串,因为 String.match
会做同样的事情。
而对于 {4}
,您只需获得两个匹配项(Trol
和 olo!
),就像在捕获 l
和 !
,同样完美。
关于javascript - 正则表达式、组和量化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17933061/