2

我的正则表达式如下(\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_">

4

3 回答 3

5

该组的每个新重复都会覆盖先前的匹配。所有的正则表达式引擎都是这样工作的。据我所知,只有 .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_"]
于 2013-11-12T21:06:44.710 回答
0

相信你想要.scan。它将返回匹配的数组。

于 2013-11-12T21:06:08.770 回答
0
"1_2_3_".scan(/\d+_/) # =>  ["1_", "2_", "3_"] 

会给你你正在寻找的东西。(注意删除*)。我还删除了分组 b/c 它只是导致一个数组数组,即[["1_"], ["2_"], ["3_"]]

于 2013-11-12T21:07:09.517 回答