与primefaces分组混淆 – 它与Ruby的正则表达式中的分组有何不同?

我刚刚浏览了Atomic Grouping和rubyinfo的文档,我想到了一些简单的问题,如下所示:

  1. 为什么这个名字是“Atomic grouping”一般分组没有什么“primefaces性”
  2. primefaces分组一般分组有何不同?
  3. 为什么primefaces组被称为非捕获组?

我尝试了下面的代码来理解,但是对输出的混淆以及它们在同一个字符串上的工作方式有多么不同?

irb(main):001:0> /a(?>bc|b)c/ =~ "abbcdabcc" => 5 irb(main):004:0> $~ => # irb(main):005:0> /a(bc|b)c/ =~ "abcdabcc" => 0 irb(main):006:0> $~ => # 

A ()有一些属性(包括诸如(?!pattern)(?=pattern)等和plain (pattern)之类的属性),但是它们之间的共同属性是分组 ,这使得任意模式成为单个单位(单位是我自己的术语),这在重复中很有用。

正常捕获(pattern)具有捕获分组的属性。 捕获意味着文本与内部模式匹配将被捕获,以便您可以在匹配或替换时使用反向引用。 非捕获组(?:pattern)没有捕获属性,因此与(pattern)相比,它将节省一点空间并加快一点,因为它不存储字符串的开始和结束索引匹配里面的模式。

primefaces分组(?>pattern)也具有非捕获属性,因此不会捕获内部匹配的文本的位置。

与捕获或非捕获组相比,primefaces分组增加了primefaces属性。 这里的primefaces意味着:在当前位置,找到第一个序列(第一个是由引擎如何根据给定的模式匹配),它与primefaces分组中的模式匹配并保持原样(因此不允许回溯)。

没有primefaces性的组将允许回溯 – 它仍然会找到第一个序列,然后如果前面的匹配失败,它将回溯并找到下一个序列,直到找到整个正则表达式的匹配或所有可能性都用尽。

输入字符串: bbabbbabbbbc
图案:/(?>。 /(?>.*)c/

由于贪婪的量词* ,第一场比赛.*bbabbbabbbbc 。 它将坚持这场比赛,禁止c匹配。 匹配器将在下一个位置重试到字符串的末尾,同样的事情发生。 所以没有什么能与正则表达式相提并论。


输入字符串: bbabbbabbbbc
模式: /((?>.*)|b*)[ac]/ ((?>。 /(((?>.*))|(b*))[ac]/ /((?>.*)|b*)[ac]/ ,用于测试/(((?>.*))|(b*))[ac]/

这个正则表达式有3个匹配,分别是bbabbbabbbbc 。 如果您使用第二个正则表达式,它是相同的但添加了捕获组以进行调试,您可以看到所有匹配都是匹配b*内部的结果。

您可以在此处查看回溯行为。

  • 如果没有primefaces分组/(.*|b*)[ac]/ ,字符串将具有单个匹配,这是整个字符串,因为在末尾回溯以匹配[ac] 。 请注意,引擎将返回.*以回溯1个字符,因为它仍有其他可能性。

     Pattern: /(.*|b*)[ac]/ bbabbbabbbbc ^ -- Start matching. Look at first item in alternation: .* bbabbbabbbbc ^ -- First match of .*, due to greedy quantifier bbabbbabbbbc X -- [ac] cannot match -- Backtrack to () bbabbbabbbbc ^ -- Continue explore other possibility with .* -- Step back 1 character bbabbbabbbbc ^ -- [ac] matches, end of regex, a match is found 
  • 通过primefaces分组, .*所有可能性都被切断并限制在第一场比赛中。 因此,在贪吃整个字符串并且无法匹配之后,引擎必须转到b*模式,在那里它成功找到与正则表达式的匹配。

     Pattern: /((?>.*)|b*)[ac]/ bbabbbabbbbc ^ -- Start matching. Look at first item in alternation: (?>.*) bbabbbabbbbc ^ -- First match of .*, due to greedy quantifier -- The atomic grouping will disallow .* to be backtracked and rematched bbabbbabbbbc X -- [ac] cannot match -- Backtrack to () -- (?>.*) is atomic, check the next possibility by alternation: b* bbabbbabbbbc ^ -- Starting to rematch with b* bbabbbabbbbc ^ -- First match with b*, due to greedy quantifier bbabbbabbbbc ^ -- [ac] matches, end of regex, a match is found 

    随后的比赛将从此处继续进行。

“primefaces组”是正则表达式永远不会回溯的过程。 所以在你的第一个例子/a(?>bc|b)c/如果组中的bc交替匹配,那么它将永远不会回溯并尝试b交替。 如果你略微改变你的第一个例子以匹配"abcdabcc"那么你会看到它仍然匹配字符串末尾的"abcc"而不是开头的"abc" 。 如果你不使用primefaces组,那么它可以回溯过bc并尝试b交替并最终匹配开头的"abc"

至于问题二,它是如何不同的,这只是对你的第一个问题的改述。

最后,primefaces组不是“被称为”非捕获组。 这不是他们的替代名称。 非捕获组是不捕获其内容的组。 通常,当您将正则表达式与字符串匹配时,您可以检索所有匹配的组,如果使用替换,则可以使用替换中的反向引用(如\1在其中插入捕获的组。 但是非捕获组不提供此function。 经典的非捕获组是(?:pattern) 。 primefaces组恰好也具有非捕获属性,因此它被称为非捕获组。

我最近不得不向其他人解释Atomic Groups,我想我会在这里调整并分享这个例子。

考虑the (big|small|biggest) (cat|dog|bird)

匹配粗体

  • 大狗
  • 小鸟
  • 最大的狗
  • 小猫

对于第一行,正则表达式引擎会找到。 然后它将继续我们的形容词( bigsmallbiggest ),它发现big 。 匹配“大”,它继续并找到空间。 然后它看着我们的宠物( catdogbird ),找到cat ,跳过它,找到dog

对于第二行,我们的正则表达式会找到。 它会继续,看看big ,跳过它,看看,发现small 。 然后它找到“”。 它看着“猫”,跳过它,看着“狗”,跳过它,发现“鸟”。

对于第三行,我们的正则表达式会找到,它继续发现并找到符合当前要求的大数据 ,然后继续。 它无法找到空间,因此它回溯 (将位置倒回到最后选择的位置)。 它跳得big ,看起来small并跳过它。 它找到最大的,也符合当前的要求 。 然后它找到“”。 它看着cat ,跳过它,并匹配dog

对于第四行,我们的正则表达式会找到。 它会继续看big ,跳过它,看看并发现small 。 然后它找到“”。 它看起来和匹配cat

现在考虑the (?>big|small|biggest) (cat|dog|bird)注意形容词上的?>primefaces组。

匹配粗体

  • 大狗
  • 小鸟
  • 最大的狗
  • 小猫

对于第一行,第二行和第四行,我们的引擎以相同的方式运行。

对于第三行,我们的正则表达式会找到,它继续并找到符合当前要求的 “大”,然后继续。 它无法找到空间,但作为引擎制造的最后选择的primefaces组将不允许重新检查选择(禁止回溯)。 由于它无法做出新的选择,因此匹配必须失败,因为我们的简单表达式没有其他选择。

这只是一个基本的总结。 引擎不需要看整个cat就知道它与dog不匹配,只看c就足够了。 当试图匹配鸟时, catc和狗中的d足以告诉引擎检查其他选项。

但是,如果你有… ((cat|snake)|dog|bird) ,当然,引擎也需要在蛇掉到前一组之前检查蛇并检查狗和鸟。

还有很多选择,引擎无法决定不经过可能看起来不匹配的东西。 如果你有((red)?cat|dog|bird) ,发动机会看“r”,退出,注意到? 量词,忽略子组(red) ,并寻找匹配。