我已经浏览了 Atomic Grouping 的文档和 rubyinfo我想到了一些问题:
- 为什么叫“原子分组”?它有什么“原子性”而一般分组没有?
- 原子分组与一般分组有何不同?
- 为什么原子组被称为非捕获组?
我尝试了下面的代码来理解,但对输出以及它们在同一字符串上的工作方式有何不同感到困惑?
irb(main):001:0> /a(?>bc|b)c/ =~ "abbcdabcc"
=> 5
irb(main):004:0> $~
=> #<MatchData "abcc">
irb(main):005:0> /a(bc|b)c/ =~ "abcdabcc"
=> 0
irb(main):006:0> $~
=> #<MatchData "abc" 1:"b">
最佳答案
()
有一些属性(包括(?!pattern)
、(?=pattern)
等属性,并且普通的(pattern)
),但它们之间的共同属性是grouping,这使得任意模式成为一个单独的单元(单元是我自己的术语),这是在重复中很有用。
普通捕获(pattern)
具有捕获和组的属性。捕获意味着将捕获与内部模式匹配的文本,以便您可以将其与反向引用一起使用,用于匹配或替换。非捕获组 (?:pattern)
没有捕获属性,所以它会比 (pattern)
节省一点空间并加快一点速度因为它不存储与内部模式匹配的字符串的开始和结束索引。
原子分组(?>pattern)
也有非捕获属性,所以里面匹配的文本的位置不会被捕获。
与捕获组或非捕获组相比,原子分组增加了原子 的属性。这里的原子意味着:在当前位置,找到与原子分组内的模式匹配的first序列(first由引擎如何根据给定的模式匹配定义)并保持它(因此回溯是不允许的)。
没有原子性的组将允许回溯 - 它仍然会找到第一个序列,然后如果前面的匹配失败,它将回溯并找到下一个序列,直到找到整个正则表达式的匹配项或用尽所有可能性.
示例
输入字符串:bbabbbbabbbbc
模式:/(?>.*)c/
由于贪婪量词 *
,.*
的第一个匹配项是 bbabbbabbbbc
。它将保留此匹配项,禁止 c
匹配。匹配器将在字符串末尾的下一个位置重试,同样的事情也会发生。所以根本没有匹配正则表达式的内容。
输入字符串:bbabbbbabbbbc
模式:/((?>.*)|b*)[ac]/
,用于测试/(((?>.*))|(b*))[ac]/
这个正则表达式有3个匹配项,分别是bba
、bbba
、bbbbc
。如果您使用第二个正则表达式,它是相同的但添加了用于调试目的的捕获组,您可以看到所有匹配项都是匹配 b*
的结果。
您可以在此处查看回溯行为。
如果没有原子分组
/(.*|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
通过原子分组,
.*
的所有可能性都被切断并限于第一个匹配项。因此,在贪婪地吃掉整个字符串并且无法匹配之后,引擎必须寻找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
后续比赛将从这里继续。
关于ruby - 与原子分组混淆 - 它与 Ruby 正则表达式中的分组有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14411818/