在Ruby中使用命名正则表达式组

时间:2014-03-01 15:58:32

标签: ruby regex

我正在尝试通过一系列线路匹配正则表达式组并且难以接受。数据文件的行如下所示:

2014-03-01 08:19,47.799107662994,-75.876391553881,some comment,James,#tag

这是我的Ruby代码:

regex = /(?<day>.*)\s(?<hour>\d*:\d*),(?<lat>.*),(?<long>.*),(?<entry>.*),(?<people>.*),#(?<tag>.*)/

f = File.open("/Users/USERNAME/path/to/file.txt", encoding: 'UTF-8')
lines = f.read
f.close
lines.each_line do |line|
  if line =~ /&/
    line.gsub!(/[&]/, 'and')
  end

  if regex =~ line
    puts line
  end
end

可行,如果我将第三个更改为最后一行,例如puts day,那么我会收到一个错误,说明这是一个未定义的局部变量。我的理解是=~自动定义了这些变量。

知道我做错了吗?

3 个答案:

答案 0 :(得分:2)

您只能通过named regex对象

访问matchdata的值
regex = /(?<day>.*)\s(?<hour>\d*:\d*),(?<lat>.*),(?<long>.*),(?<entry>.*),(?<people>.*),#(?<tag>.*)/
line = "2014-03-01 08:19,47.799107662994,-75.876391553881,some comment,James,#tag"

matchdata = regex.match(line)

matchdata["day"] # => "2014-03-01"

so I would do as below instead:

if (matchdata = regex.match(line))
  puts matchdata["day"]
end

答案 1 :(得分:2)

来自Ruby Rexexp docs

  

当命名捕获组与表达式左侧的文字正则表达式和=〜运算符一起使用时,捕获的文本也会分配给具有相应名称的局部变量。

所以它需要是一个 literal 正则表达式,用于创建局部变量。

在您的情况下,您使用变量来引用正则表达式,而不是文字。

例如:

regex = /(?<day>.*)/
regex =~ 'whatever'
puts day

生成NameError: undefined local variable or method `day' for main:Object,但是这个

/(?<day>.*)/ =~ 'whatever'
puts day

打印whatever

答案 2 :(得分:0)

尝试:

puts $~['day'] if regex =~ line

(有点神秘)$~全局变量是一个MatchData实例,用于存储最后一个正则表达式匹配的结果,您可以在那里访问您的命名捕获。

但@bjhaid的答案是更好的选择,明确保存MatchData。