正则表达式、组和量化器

Posted

技术标签:

【中文标题】正则表达式、组和量化器【英文标题】:Regex, group & quantifyer 【发布时间】:2013-07-29 18:36:59 【问题描述】:

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

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

要匹配的字符串是“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: ! 

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

【问题讨论】:

什么是JSJS'?有什么区别? 我认为该网站没有为您提供正确的组。请改用regexplanet.com。 【参考方案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 给出一个二维数组,其中第一个索引对应于组,第二个对应于匹配。在您的输出中,它被反过来解释。因此,当有多个匹配时,第一对01 是两个找到的匹配的整个匹配。第二对 01 是您在这两场比赛中捕获的。

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

对于4,您只需获得两个匹配项(Trololo!),就像在 JavaScript 案例中分别捕获 l! 一样,这同样非常好。

【讨论】:

> 首先,应该发生什么?确实,这就是问题:-)我实际上预期,在 abcd 上匹配 (.)* 将给出 0.abcd 1.a 2.b 3.c 4.d - 也就是说,我得到更多组,正如量词所显示的那样量化组。但想了很久,这似乎根本不可用,因为组引用是固定的。 @Falko,唯一能做到这一点的正则表达式风格是 .NET。在那里,您会为每个包含 Capture 集合的组获得一个 Group 对象。 啊,酷。但如前所述,我无法想象这在实践中有何帮助。 @Falko 说你有类似...(13|52|78|33)... 的东西,并且想要匹配所有数字,但可能是任意数量。另一种方法是两步匹配,您首先匹配序列,然后将其拆分或其他方式。但在 .NET 中,您可以立即捕获所有这些数字。 .NET 实际上走得更远,这些捕获被保存在堆栈中,在匹配过程中元素可以在堆栈中弹出,这允许在正则表达式中进行计数:[参见平衡组](***.com/questions/17003799/what-are-regular -表达式平衡组)

以上是关于正则表达式、组和量化器的主要内容,如果未能解决你的问题,请参考以下文章

基于词汇和正则表达式矢量化文档

您如何使用正则表达式“量化”可变数量的行?

无捕获组和命名组

正则表达式练习

什么时间用正则表达式什么时间用json提取器

用户管理和正则表达式