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

drK*_*eso 5 ruby regex string alternation regex-alternation

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

如果这是我的字符串:

????????????????
Run Code Online (Sandbox Code Playgroud)

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

(?????????????|??)
Run Code Online (Sandbox Code Playgroud)

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

?????????????
Run Code Online (Sandbox Code Playgroud)

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

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

如果这是我的字符串:

foobar
Run Code Online (Sandbox Code Playgroud)

我使用这个正则表达式:

(foobar|foo)
Run Code Online (Sandbox Code Playgroud)

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

Uni*_*ron 15

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

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

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

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

(cdefghijkl|bcd)
Run Code Online (Sandbox Code Playgroud)

你的字符串上的另一个:

abcdefghijklmnopqrstuvw
Run Code Online (Sandbox Code Playgroud)

String上的指针从左侧移动.只要它可以返回,它将会:

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

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

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

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

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

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

看!*

^(?:.*?\Kcdefghijkl|.*?\Kbcd)
Run Code Online (Sandbox Code Playgroud)

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

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


*:\K从2.0.0开始在Ruby中得到支持.

阅读更多:





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

^(?:(?:(?!cdefghijkl)c?[^c]*)++\Kcdefghijkl|(?:(?!bcd)b?[^b]*)++\Kbcd)
Run Code Online (Sandbox Code Playgroud)

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

  • 精彩的文章......包括OP问题的简单答案(`正则表达式如何工作:状态机总是从左到右读取,必要时回溯.)以及优化的表达式. (2认同)