为什么ruby只返回正则表达式的最后一个匹配?

时间:2013-11-12 21:03:31

标签: ruby regex

我的正则表达式是以下(\d+_)*,测试字符串是1_2_3_。 Ruby正确匹配字符串。但是,matchdata仅返回“3_”作为匹配。

e.g。

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_">

之类的东西

3 个答案:

答案 0 :(得分:4)

该组的每次重复都会覆盖上一场比赛。所有正则表达式引擎都以这种方式工作。据我所知,只有.NET正则表达式引擎提供了一种访问重复组的所有匹配的方法(所谓的“捕获”)。

想象一下发生了什么。在正则表达式中,每对括号都构建一个捕获组;它们从左到右编号。因此,在/(\d+_)*/中,(\d+_)正在捕获第1组。

现在,如果您将该正则表达式应用于1_2_,会发生什么?

  • (\d+_)匹配1_
  • 1_被存储为第一个捕获组的内容。您现在可以访问\1以查看这些内容。
  • *告诉正则表达式引擎从当前位置重试匹配。
  • (\d+_)现在匹配2_
  • 该文字2_再次需要存储在第1组/反向引用\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_"]

答案 1 :(得分:0)

我相信你想要.scan。它将返回一系列匹配。

答案 2 :(得分:0)

"1_2_3_".scan(/\d+_/) # =>  ["1_", "2_", "3_"] 

将为您提供所需的信息。 (注意删除*)。我还删除了分组b / c,它只是产生一个数组数组,即[["1_"], ["2_"], ["3_"]]