Leonid Shevtsov
Leonid Shevtsov

Reputation: 14189

Is there a function like String#scan, but returning array of MatchDatas?

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

Upvotes: 7

Views: 2066

Answers (4)

Mike McKay
Mike McKay

Reputation: 2656

Use the captures method on a successful match.

"foobar".match(/(f)(oobar)/).captures

=> ["f,""oobar"]

Upvotes: 1

khelll
khelll

Reputation: 24010

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

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

Upvotes: 0

Jonas Elfstr&#246;m
Jonas Elfstr&#246;m

Reputation: 31438

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!"

Upvotes: 2

sepp2k
sepp2k

Reputation: 370357

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 }

Upvotes: 11

Related Questions