为什么交替中不会有更长的令牌匹配?
我正在使用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)
你可以在这里看到一个演示。