Regexp exercise

O

Olivier D.

Hi,
I have a string from which I want to extract a value. I have found four
different methods to do it:

string = "a: 1, b: 2, c: 3"
# let's say I want the value associated with b (2)

# 1st method:
value = string[/b: \d+/][/\d+/]

# 2nd method:
value = string.scan(/b: (\d+)/)[0][0]

# 3rd method:
value = nil
string.scan(/b: (\d+)/) { |val| value = val }

These three methods aren't clean and easy to understand.

I think that the best way to do it would be to use a simple match
operator like:
value = $1 if string =~ /b: (\d+)/

But on a different thread (http://tinyurl.com/38b27) someone explained
that using global variables was a bad habit not to take.

What should I do? Is the $1 method *that* bad? (after all, I just use it
inside the 'if' loop...)
 
C

Carlos

Hi,
I have a string from which I want to extract a value. I have found four
different methods to do it:

string = "a: 1, b: 2, c: 3"
# let's say I want the value associated with b (2)

# 1st method:
value = string[/b: \d+/][/\d+/]

# 2nd method:
value = string.scan(/b: (\d+)/)[0][0]

# 3rd method:
value = nil
string.scan(/b: (\d+)/) { |val| value = val }

These three methods aren't clean and easy to understand.

I think that the best way to do it would be to use a simple match
operator like:
value = $1 if string =~ /b: (\d+)/

But on a different thread (http://tinyurl.com/38b27) someone explained
that using global variables was a bad habit not to take.

What should I do? Is the $1 method *that* bad? (after all, I just use it
inside the 'if' loop...)

I don't find it bad, but if you want to avoid it you can do

matchdata=/b: (\d+)/.match(string) and value=matchdata[1]
 
O

Olivier D.

What should I do? Is the $1 method *that* bad? (after all, I just use it
inside the 'if' loop...)

I don't find it bad, but if you want to avoid it you can do

matchdata=/b: (\d+)/.match(string) and value=matchdata[1]

Thanks for the advice. It's just that it took me two days to remember
that the groups of a pattern are put in $1..$9 with the =~ operator.

I discovered that $1 can have two different values:
- nil if a number is not found
- the number found if it exists
Which means: no errors possible from a previous match. $1 has his value
changed every time.
 
O

Olivier D.

O> value = string[/b: \d+/][/\d+/]

value = string[/b: (\d+)/, 1]

Guy Decoux

Wonderful, exactly the "hacker's way" I was looking for.
This feature is not on the (rather old) documentation I was looking at.
I think it's time for me to dig into Ruby's source code...
 
D

David A. Black

Hi --

Hi,
I have a string from which I want to extract a value. I have found four
different methods to do it:

string = "a: 1, b: 2, c: 3"
# let's say I want the value associated with b (2)

# 1st method:
value = string[/b: \d+/][/\d+/]

# 2nd method:
value = string.scan(/b: (\d+)/)[0][0]

# 3rd method:
value = nil
string.scan(/b: (\d+)/) { |val| value = val }

These three methods aren't clean and easy to understand.

I think that the best way to do it would be to use a simple match
operator like:
value = $1 if string =~ /b: (\d+)/

In addition to the other answers, if you want to grab the value as an
integer, you could do:

require 'scanf'
str = "a: 1, b: 2, c: 3"
val, = str.scanf("%*[^b]b: %d")
p val # => 2


David
 
D

David A. Black

Hi --

"O" == Olivier D <nkh@SP_tele2_AM.fr> writes:

O> value = string[/b: \d+/][/\d+/]

value = string[/b: (\d+)/, 1]

Guy Decoux

Wonderful, exactly the "hacker's way" I was looking for.
This feature is not on the (rather old) documentation I was looking at.
I think it's time for me to dig into Ruby's source code...

You'll find this documented in ri. (Not that I want to discourage you
from looking at the source too :)


David
 
R

Robert

Olivier D. wrote:

I think that the best way to do it would be to use a simple match
operator like:
value = $1 if string =~ /b: (\d+)/

But on a different thread (http://tinyurl.com/38b27) someone explained
that using global variables was a bad habit not to take.

I'm not 100% but as far as I remember $1 is thread local, i.e. no two
threads can interfere with each other if they match regular expressions
at the same time. In that case it would be save to use $1. Can anybod
comment on that?

Kind regards

robert
 

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

Members online

Forum statistics

Threads
474,147
Messages
2,570,835
Members
47,383
Latest member
EzraGiffor

Latest Threads

Top