Ruby String#Scan Equivalent to Return Matchdata

Ruby String#scan equivalent to return MatchData

You could easily build your own by exploiting MatchData#end and the pos parameter of String#match. Something like this:

def matches(s, re)
start_at = 0
matches = [ ]
while(m = s.match(re, start_at))
matches.push(m)
start_at = m.end(0)
end
matches
end

And then:

>> matches("foo _bar_ _baz_ hashbang", /_[^_]+_/)
=> [#<MatchData "_bar_">, #<MatchData "_baz_">]
>> matches("_a_b_c_", /_[^_]+_/)
=> [#<MatchData "_a_">, #<MatchData "_c_">]
>> matches("_a_b_c_", /_([^_]+)_/)
=> [#<MatchData "_a_" 1:"a">, #<MatchData "_c_" 1:"c">]
>> matches("pancakes", /_[^_]+_/)
=> []

You could monkey patch that into String if you really wanted to.

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

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 }

Matching position in gsub or scan

"hello".gsub(/./) { Regexp.last_match.offset(0).first }
=> "01234"

See Regexp.last_match and MatchData.

Get index of string scan results in ruby

Try this:

res = []
"abab".scan(/a/) do |c|
res << [c, $~.offset(0)[0]]
end

res.inspect # => [["a", 0], ["a", 2]]

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

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.

What's the difference between scan and match on Ruby string

Short answer: scan will return all matches. This doesn't make it superior, because if you only want the first match, str.match[2] reads much nicer than str.scan[0][1].

ruby-1.9.2-p290 :002 > 'a 1-night stay, a 2-night stay'.scan(/(a )?(\d*)[- ]night/i).to_a
=> [["a ", "1"], ["a ", "2"]]
ruby-1.9.2-p290 :004 > 'a 1-night stay, a 2-night stay'.match(/(a )?(\d*)[- ]night/i).to_a
=> ["a 1-night", "a ", "1"]

How to access the results of .match as string value in Crystal lang

What if I want to convert to a string merely the first match?

puts "Happy days"[/[a-z]+/i]?
puts "Happy days".match(/[a-z]+/i).try &.[0]

It will try to match a string against /[a-z]+/i regex and if there is a match, Group 0, i.e. the whole match, will be output. Note that the ? after [...] will make it fail gracefully if there is no match found. If you just use puts "??!!"[/[a-z]+/i], an exception will be thrown.

See this online demo.

If you want the functionality similar to String#scan that returns all matches found in the input, you may use (shortened version only left as per @Amadan's remark):

matches = str.scan(re).map(&.string)

Output of the code above:

["Happy days", "Happy days"]

Note that:

  • String::scan will return an array of Regex::MatchData for each match.
  • You can call .string on the match to return the actual matched text.

How to match all occurrences of a regular expression in Ruby

Using scan should do the trick:

string.scan(/regex/)


Related Topics



Leave a reply



Submit