首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不同Ruby版本的扫描和匹配行为的差异

不同Ruby版本的扫描和匹配行为的差异
EN

Stack Overflow用户
提问于 2017-03-24 19:46:03
回答 1查看 111关注 0票数 3

背景

这个问题涉及到Ruby中String#scanString#match方法的行为。我使用的是一个递归正则表达式,它应该与一个平衡的大括号匹配。您可以在:https://regex101.com/r/Q1lOC8/1上看到这个正则表达式https://regex101.com/r/Q1lOC8/1的作用。在这里,它显示了预期的行为:匹配具有平衡的嵌套括号集的顶级括号集。说明此问题的一些示例代码如下:

代码语言:javascript
运行
复制
➜  cat test.rb                                                                          
s = "1+(x*(3-4)+5)-1"
r = /(\((?:[^\(\)]*\g<0>*)*\))/
puts s.match(r).inspect
puts s.scan(r).inspect

问题

当在ruby-2.3.3和ruby-2.4.1中运行上述示例代码时,我得到了不同的结果:

代码语言:javascript
运行
复制
➜  docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app ruby:2.3.3-alpine ruby test.rb
#<MatchData "(x*(3-4)+5)" 1:")">
[[")"]]
➜  docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app ruby:2.4.1-alpine ruby test.rb
#<MatchData "(x*(3-4)+5)" 1:"(x*(3-4)+5)">
[["(x*(3-4)+5)"]]

红宝石-2.4.1的情况正是我所期待的。在这两种情况下,match都正确地匹配了相同的括号集,(x*(3-4)+5),但是在ruby-2.3.3中,由于某种原因,第一组匹配就是")"。如果我将正则表达式更改为/(\(.*\))/,那么这两个版本的行为是相同的(与上面的2.4.1相同),但它将不再确保嵌套大括号是平衡的。

在这种情况下,match的真正预期行为是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-24 20:54:50

首先,我应该注意,在regex101.com上工作的东西不需要在任何地方工作:在在线regex测试器的帮助下编写的任何regex都必须在目标环境中进行测试。您使用PCRE选项进行了测试,并且它成功了,因为PCRE是一个与Ruby中使用的Onigmo不同的库。

现在,问题似乎是Onigmo引擎如何处理2.3.3中的递归:\g<0>构造递归整个模式(第0组),外部捕获括号(第1组)也被重复(其ID保持不变),从而有效地创建了重复捕获组。这些组中的值在每次迭代时都会重写,这就是为什么最终得到)的原因。

所做的工作是递归Group 1子模式,使Group 1值保持完整,而无需在每次迭代时重写它的值(因为捕获组是在模式中定义的,所以String#scan只返回捕获)。

使用

代码语言:javascript
运行
复制
r = /(\((?:[^\(\)]*\g<1>*)*\))/
                      ^
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43007936

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档