Regular expression question

D

DeZo

Why does the following code:

line = " rows = 10 cols = 1 occupied cells = 0"
line =~ /.*(\d+).*(\d+).*(\d+)/
print(" scanned rows = ",$1," cols = ",$2," occ = ",$3,"\n")

print this when it runs:

scanned rows = 0 cols = 1 occ = 0

(notice rows is zero!)

What have I done wrong?
 
R

Robert Klemme

Ross said:
Why does the following code:

line = " rows = 10 cols = 1 occupied cells = 0"
line =~ /.*(\d+).*(\d+).*(\d+)/
print(" scanned rows = ",$1," cols = ",$2," occ = ",$3,"\n")

print this when it runs:

scanned rows = 0 cols = 1 occ = 0

(notice rows is zero!)

What have I done wrong?

Your problem is that '*' is greedy so it'll match as many 'any
characters' as it can. Try

/.*?(\d+).*?(\d+).*?(\d+)/

Usually I'd tend to use something like:

/[^\d]*(\d+)[^\d]*(\d+)[^\d]*(\d+)/

instead, to make it explicit I want not digits, followed by digits,
etc...

Some other solutions with individual pros and cons:
line = " rows = 10 cols = 1 occupied cells = 0" => " rows = 10 cols = 1 occupied cells = 0"
line.scan(/\d+/) => ["10", "1", "0"]
line.scan(/\d+/).map {|s| s.to_i} => [10, 1, 0]
line.scan(/\w+\s*=\s*(\d+)/) => [["10"], ["1"], ["0"]]
line.scan(/\w+\s*=\s*(\d+)/).map {|m| m[0].to_i}
=> [10, 1, 0]

And explicitely matching the pattern:
line and [$1, $2, $3]
=> ["10", "1", "0"]line and [$1.to_i, $2.to_i, $3.to_i]
=> [10, 1, 0]

Kind regards

robert
 
J

Jim

I've been using this idiom recently.
line = " rows = 10 cols = 1 occupied cells = 0" => " rows = 10 cols = 1 occupied cells = 0"
if line[/.*?(\d+).*?(\d+).*?(\d+)/]
rows, cols, cells = $1.to_i, $2.to_i, $3.to_i
end => [10, 1, 0]
rows => 10
cols => 1
cells
=> 0
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,162
Latest member
GertrudeMa
Top