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

时间:2014-08-26 17:13:34

标签: ruby regex string alternation regex-alternation

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

如果这是我的字符串:

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

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

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

我希望得到更长的令牌作为匹配。

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

相反,我将第二次轮换作为匹配。

据我所知,当不是中文字符时,它确实有效。

如果这是我的字符串:

foobar

我使用这个正则表达式:

(foobar|foo)

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

1 个答案:

答案 0 :(得分:15)

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

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

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

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

(cdefghijkl|bcd)

你的字符串上的另一个:

abcdefghijklmnopqrstuvw

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

x http://gyazo.com/ac652df1ed094be6c5d66c14a2728ac1.png

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

y http://gyazo.com/386aecb351fc2eb34f9c5db269a66dab.png

您的foobar示例是另一个主题。正如我提到的in this post

  

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

这很好,Unihedron,但是如何强制它进行第一次轮换呢?

看<!SUP> *

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

这里有regex demo

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


*:从2.0.0开始,Ruby支持\K

了解详情:





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

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

您可以看到演示here