tags:

views:

85

answers:

3

I need a function to return all matches of a regexp in a string and positions at which the matches are found (I want to highlight matches in the string).

There is String#match that returns MatchData, but only for the first match.

Is there a better way to do this than something like

matches = []
begin
  match = str.match(regexp)
  break unless match
  matches << match
  str = str[match.end(0)..-1]
  retry
end
+3  A: 

If you just need to iterate over the MatchData objects you can use Regexp.last_match in the scan-block, like:

string.scan(regex) do
  match_data = Regexp.last_match
  do_something_with(match_data)
end

If you really need an array, you can use:

require 'enumerator' # Only needed for ruby 1.8.6
string.enum_for(:scan, regex).map { Regexp.last_match }
sepp2k
Thanks, I didn't know about Regexp.last_match
Leonid Shevtsov
+1 for enum_for, thanks for sharing!
khelll
+2  A: 

Do you really need the position or is it enough to replace the matches on the fly?

s="I'mma let you finish but Beyonce had one of the best music videos of all time!"
s.gsub(/(Beyonce|best)/, '<b>\1</b>')

=> "I'mma let you finish but Beyonce had one of the best music videos of all time!"

Jonas Elfström
Nah, I only know what needs to be highlighted after the string is parsed and analyzed.
Leonid Shevtsov
It sure looks like you are using Regexp for the parsing and so does gsub.
Jonas Elfström
A: 

I think at least you can enhance your code a bit:

matches = []
while(match = str.match(regexp)) 
  matches << match
  str = match.post_match
end
khelll