Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby one-liner to capture regular expression matches

Tags:

regex

ruby

In Perl, I use the following one line statements to pull matches out of a string via regular expressions and assign them. This one finds a single match and assigns it to a string:

my $string = "the quick brown fox jumps over the lazy dog.";

my $extractString = ($string =~ m{fox (.*?) dog})[0];

Result: $extractString == 'jumps over the lazy'

And this one creates an array from multiple matches:

my $string = "the quick brown fox jumps over the lazy dog.";

my @extractArray = $string =~ m{the (.*?) fox .*?the (.*?) dog};

Result: @extractArray == ['quick brown', 'lazy']

Is there an equivalent way to create these one-liners in Ruby?

like image 557
Alan W. Smith Avatar asked Jan 08 '14 15:01

Alan W. Smith


People also ask

How do you match expressions in regex?

To match a character having special meaning in regex, you need to use a escape sequence prefix with a backslash ( \ ). E.g., \. matches "." ; regex \+ matches "+" ; and regex \( matches "(" . You also need to use regex \\ to match "\" (back-slash).

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 is \r and \n in regex?

Matches a form-feed character. \n. Matches a newline character. \r. Matches a carriage return character.

What does $1 do in regex?

The $ number language element includes the last substring matched by the number capturing group in the replacement string, where number is the index of the capturing group. For example, the replacement pattern $1 indicates that the matched substring is to be replaced by the first captured group.


2 Answers

string = "the quick brown fox jumps over the lazy dog."

extract_string = string[/fox (.*?) dog/, 1]
# => "jumps over the lazy"

extract_array = string.scan(/the (.*?) fox .*?the (.*?) dog/).first
# => ["quick brown", "lazy"]

This approach will also return nil (instead of throwing an error) if no match is found.

extract_string = string[/MISSING_CAT (.*?) dog/, 1]
# => nil

extract_array = string.scan(/the (.*?) MISSING_CAT .*?the (.*?) dog/).first
# => nil
like image 131
sawa Avatar answered Sep 22 '22 07:09

sawa


Use String#match and MatchData#[] or MatchData#captures to get matched backreferences.

s = "the quick brown fox jumps over the lazy dog."

s.match(/fox (.*?) dog/)[1]
# => "jumps over the lazy"
s.match(/fox (.*?) dog/).captures
# => ["jumps over the lazy"]

s.match(/the (.*?) fox .*?the (.*?) dog/)[1..2]
# => ["quick brown", "lazy"]
s.match(/the (.*?) fox .*?the (.*?) dog/).captures
# => ["quick brown", "lazy"]

UPDATE

To avoid undefined method [] error:

(s.match(/fox (.*?) cat/) || [])[1]
# => nil
(s.match(/the (.*?) fox .*?the (.*?) cat/) || [])[1..2]
# => nil
(s.match(/the (.*?) fox .*?the (.*?) cat/) || [])[1..-1] # instead of .captures
# => nil
like image 24
falsetru Avatar answered Sep 19 '22 07:09

falsetru