简体   繁体   中英

Working with Named Regex Groups in Ruby

I'm trying to match regex groups over a series of lines and getting stumped. Data file has lines that look like this:

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

Here is my Ruby code:

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

That works, but if I change that third to last to line to, for example puts day , then I get an error saying that is an undefined local variable. My understanding was that =~ automatically defined those variables.

Any idea what I'm doing wrong?

You can only access value of the named regex through a matchdata object

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

From the Ruby Rexexp docs :

When named capture groups are used with a literal regexp on the left-hand side of an expression and the =~ operator, the captured text is also assigned to local variables with corresponding names.

So it needs to be a literal regex that is used in order to create the local variables.

In your case you are using a variable to reference the regex, not a literal.

For example:

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

produces NameError: undefined local variable or method `day' for main:Object , but this

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

prints whatever .

Try:

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

The (somewhat cryptic) $~ global variable is a MatchData instance storing the results of the last regex match, and you can access your named captures in there.

But the answer by @bjhaid is a better choice, saving the MatchData explicitly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM