Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Regexp group matching, assign variables on 1 line

I'm currently trying to rexp a string into multiple variables. Example string:

ryan_string = "RyanOnRails: This is a test" 

I've matched it with this regexp, with 3 groups:

ryan_group = ryan_string.scan(/(^.*)(:)(.*)/i) 

Now to access each group I have to do something like this:

ryan_group[0][0] (first group) RyanOnRails ryan_group[0][1] (second group) : ryan_group[0][2] (third group) This is a test 

This seems pretty ridiculous and it feels like I'm doing something wrong. I would be expect to be able to do something like this:

g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i) 

Is this possible? Or is there a better way than how I'm doing it?

like image 540
ryanjones Avatar asked Feb 16 '12 00:02

ryanjones


People also ask

What is the difference between a match and group in regex?

A Match is an object that indicates a particular regular expression matched (a portion of) the target text. A Group indicates a portion of a match, if the original regular expression contained group markers (basically a pattern in parentheses).

What does =~ mean in Ruby regex?

=~ is Ruby's basic pattern-matching operator. When one operand is a regular expression and the other is a string then the regular expression is used as a pattern to match against the string. (This operator is equivalently defined by Regexp and String so the order of String and Regexp do not matter.

What method should you use when you want to get all sequences matching a regex pattern in a string?

To find all the matching strings, use String's scan method.

How do you match a string in Ruby?

Ruby | Regexp match() functionRegexp#match() : force_encoding?() is a Regexp class method which matches the regular expression with the string and specifies the position in the string to begin the search. Return: regular expression with the string after matching it.


2 Answers

You don't want scan for this, as it makes little sense. You can use String#match which will return a MatchData object, you can then call #captures to return an Array of captures. Something like this:

#!/usr/bin/env ruby  string = "RyanOnRails: This is a test" one, two, three = string.match(/(^.*)(:)(.*)/i).captures  p one   #=> "RyanOnRails" p two   #=> ":" p three #=> " This is a test" 

Be aware that if no match is found, String#match will return nil, so something like this might work better:

if match = string.match(/(^.*)(:)(.*)/i)   one, two, three = match.captures end 

Although scan does make little sense for this. It does still do the job, you just need to flatten the returned Array first. one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten

like image 61
Lee Jarvis Avatar answered Oct 22 '22 13:10

Lee Jarvis


You could use Match or =~ instead which would give you a single match and you could either access the match data the same way or just use the special match variables $1, $2, $3

Something like:

if ryan_string =~ /(^.*)(:)(.*)/i    first = $1    third = $3 end 
like image 22
Rado Avatar answered Oct 22 '22 13:10

Rado