gpt4 book ai didi

ruby - 不同 Ruby 版本的 `scan` 和 `match` 行为存在差异

转载 作者:数据小太阳 更新时间:2023-10-29 08:07:01 26 4
gpt4 key购买 nike

背景

这个问题是关于 String#scan 的行为的和 String#match Ruby 中的方法。我正在使用递归正则表达式,它应该匹配一对平衡的大括号。可以看到这个正则表达式/(\((?:[^\(\)]*\g<0>*)*\))/在行动中:https://regex101.com/r/Q1lOC8/1 .它在那里显示预期的行为:匹配具有平衡的嵌套括号集的顶级括号集。一些说明该问题的示例代码如下:

➜  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 中运行上述示例代码时得到不同的结果:

➜  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)"]]

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

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

最佳答案

首先,我应该指出,在 regex101.com 上有效的东西不一定在任何地方都有效:在在线正则表达式测试器的帮助下编写的任何正则表达式必须在目标环境中进行测试。您使用 PCRE 选项进行了测试,它起作用了,因为 PCRE 是一个不同于 Ruby 中使用的 Onigmo 的库。

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

解决方法是递归第 1 组子模式以完整保留第 1 组值,而无需在每次迭代时重写其值(由于模式中定义了捕获组,String#scan 仅返回 capture( s)).

使用

r = /(\((?:[^\(\)]*\g<1>*)*\))/
^

关于ruby - 不同 Ruby 版本的 `scan` 和 `match` 行为存在差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43007936/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com