5

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

如果这是我的字符串:

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

我用这个表达式做一个正则表达式匹配:

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

我期望获得更长的令牌作为匹配项。

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

相反,我得到了第二个交替作为匹配。

据我所知,当不是中文字符时,它确实可以这样工作。

如果这是我的字符串:

foobar

我使用这个正则表达式:

(foobar|foo)

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

4

1 回答 1

15

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

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

快速复习:正则表达式的工作原理:状态机总是从左到右读取,必要时回溯。

有两个指针,一个在 Pattern 上:

(cdefghijkl|bcd)

你的字符串上的另一个:

abcdefghijklmnopqrstuvw

字符串上的指针从左边移动。一旦它可以返回,它将

X
(来源:gyazo.com

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

是的
(来源:gyazo.com

你的foobar例子是一个不同的话题。正如我在这篇文章中提到的:

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

    很好,Unihedron,但我如何强制它进入第一个交替?

看!*

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

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

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


*\K自 2.0.0 起在 Ruby 中得到支持。

阅读更多:





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

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

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

于 2014-08-26T17:19:48.897 回答