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 ofRegex::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
Checking If Activerecord Find Returns a Result
Factory_Girl + Rspec Doesn't Seem to Roll Back Changes After Each Example
How to Use Present? in Ruby Projects
Generate String for Regex Pattern in Ruby
How to Completely Remove Webpack and All Its Dependencies from Rails App
Generating Sequential Numbers in Multi-User Saas Application
Emacs Ruby Method Parameter Indentation
Colon in the Front: Yaml Syntax
Cloning an Array with Its Content
Devise Not Working Well with Multiple Subdomains on Ror3 Application
How to Profile Rspec with Perftools and Bundler
Dynamically Get Object's Attribute
Get Available Diskspace in Ruby
In Depth Ruby Gem Development Resources (Book, Video, Sites)
Fresh Install of Rvm in Ubuntu Isn't Letting Me Install Gems (Zlib Error)
Can You Create/Write/Append a String to a File in a Single Line in Ruby