我的正则表达式如下(\d+_)*
,测试字符串是1_2_3_
. Ruby 正确匹配字符串。但是,matchdata 仅返回“3_”作为匹配项。
例如
irb(main):004:0> /(\d+_)*/.match("1_2_3_")
=> #<MatchData "1_2_3_" 1:"3_">
我期待类似的东西 #<MatchData "1_2_3_" 1:"1_", 2:"2_", 3:"3_">
该组的每个新重复都会覆盖先前的匹配。所有的正则表达式引擎都是这样工作的。据我所知,只有 .NET 正则表达式引擎提供了一种访问重复组的所有匹配项的方法(所谓的“捕获”)。
想象一下正在发生的事情。在正则表达式中,每对括号都构建一个捕获组;它们从左到右编号。因此,在 中/(\d+_)*/
,(\d+_)
正在捕获第 1 组。
现在,如果您将该正则表达式应用于1_2_
,会发生什么?
(\d+_)
火柴1_
1_
存储为第一个捕获组的内容。您现在可以访问\1
查看这些内容。*
则表达式引擎从当前位置重试匹配。(\d+_)
现在匹配2_
2_
再次需要存储在组号 1/backreference\1
中。所以它会覆盖那里的任何东西。要在 Ruby 中获得所需的结果,您需要执行两个正则表达式匹配:/(?:\d+_)*/
针对整体匹配和/\d+_/
每个单独匹配:
irb(main):001:0> s = "1_2_3_"
=> "1_2_3_"
irb(main):009:0> s.match(/(?:\d+_)*/)
=> #<MatchData "1_2_3_">
irb(main):007:0> s.scan(/\d+_/)
=> ["1_", "2_", "3_"]
相信你想要.scan
。它将返回匹配的数组。
"1_2_3_".scan(/\d+_/) # => ["1_", "2_", "3_"]
会给你你正在寻找的东西。(注意删除*
)。我还删除了分组 b/c 它只是导致一个数组数组,即[["1_"], ["2_"], ["3_"]]