为什么交替中不会有更长的令牌匹配?

我正在使用ruby 2.1,但同样的东西可以在rubular网站上复制。

如果这是我的字符串:

儘管中國婦幼衛生監測辦公室制定的 

我用这个表达式进行正则表达式匹配:

 (中國婦幼衛生監測辦公室制定|管中) 

我期待得到更长的令牌作为匹配。

 中國婦幼衛生監測辦公室制定 

相反,我得到了第二次替换作为匹配。

据我所知,它不像中文字符那样工作。

如果这是我的字符串:

 foobar 

我使用这个正则表达式:

 (foobar|foo) 

返回的匹配结果是foobar 。 如果顺序是另一种方式,那么匹配的字符串就是foo 。 这对我来说很有意义。

您认为正则表达式匹配较长的交替是不正确的。

如果你有一点时间,让我们来看看你的正则表达式如何运作……

快速复习:正则表达式如何工作:状态机始终从左到右读取,必要时回溯。

有两个指针,一个在模式上:

 (cdefghijkl|bcd) 

你的字符串上的另一个:

 abcdefghijklmnopqrstuvw 

String上的指针从左侧移动。 一旦它可以返回,它将:

x http://sofzh.miximages.com/ruby/ac652df1ed094be6c5d66c14a2728ac1.png

让我们把它变成一个更“顺序”的序列来理解:

y http://sofzh.miximages.com/ruby/386aecb351fc2eb34f9c5db269a66dab.png

您的foobar示例是另一个主题。 正如我在这篇文章中提到的 :

正则表达式的工作原理:状态机始终从左到右读取。 ,|,, == ,因为它始终只与第一次交替匹配。

那是好的,Unihedron,但是如何强制它进行第一次交替呢?

看! *

 ^(?:.*?\Kcdefghijkl|.*?\Kbcd) 

这里有一个正则表达式演示 。

此正则表达式首先尝试将整个字符串与第一个交替进行匹配。 只有当它完全失败时,它才会尝试匹配第二次交替。 这里使用\K保持与构造\K 后面的内容的匹配。


*\K 2.0从2.0.0开始在Ruby中得到支持。

阅读更多:

  • Stack Overflow Regex参考
  • 贪婪与非贪婪

啊,我很无聊,所以我优化了正则表达式:

 ^(?:(?:(?!cdefghijkl)c?[^c]*)++\Kcdefghijkl|(?:(?!bcd)b?[^b]*)++\Kbcd) 

你可以在这里看到一个演示。