Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the match data for all occurrences of a Ruby regular expression in a string?

Tags:

regex

ruby

I need the MatchData for each occurrence of a regular expression in a string. This is different than the scan method suggested in Match All Occurrences of a Regex, since that only gives me an array of strings (I need the full MatchData, to get begin and end information, etc).

input = "abc12def34ghijklmno567pqrs" numbers = /\d+/  numbers.match input # #<MatchData "12"> (only the first match) input.scan numbers  # ["12", "34", "567"] (all matches, but only the strings) 

I suspect there is some method that I've overlooked. Suggestions?

like image 485
Joshua Flanagan Avatar asked Jul 24 '11 02:07

Joshua Flanagan


People also ask

How do I find all matches in regex?

To find find all the matches of a regular expression in this string in JavaScript, call match() method on this string, and pass the regular expression as argument. match() method returns an array of strings containing all the matches found for the given regular expression, in this string.

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?

=~ 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 regex returns a list of strings containing all matches?

Regex's findall() function is extremely useful as it returns a list of strings containing all matches.


2 Answers

You want

"abc12def34ghijklmno567pqrs".to_enum(:scan, /\d+/).map { Regexp.last_match } 

which gives you

[#<MatchData "12">, #<MatchData "34">, #<MatchData "567">]  

The "trick" is, as you see, to build an enumerator in order to get each last_match.

like image 67
i-blis Avatar answered Oct 05 '22 22:10

i-blis


My current solution is to add an each_match method to Regexp:

class Regexp   def each_match(str)     start = 0     while matchdata = self.match(str, start)       yield matchdata       start = matchdata.end(0)     end   end end 

Now I can do:

numbers.each_match input do |match|   puts "Found #{match[0]} at #{match.begin(0)} until #{match.end(0)}" end 

Tell me there is a better way.

like image 38
Joshua Flanagan Avatar answered Oct 05 '22 22:10

Joshua Flanagan