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 }
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.
Looking for Regexp#match_all
See Is there a function like String#scan, but returning array of MatchDatas?
It looks like your best bet is to use String#scan
and Regexp.last_match
.
String.scan returning empty array in Ruby
The main issue is that your capturing groups (the stuff matched by whatever's in parentheses) aren't capturing what you want.
Let's say you want just the username and domain. You should use something along the lines of /\b(\w+(?:\.\w+)*)@(\w+(?:\.\w+)*)\.\w+\b/
. As it stands, your pattern matches the input text, but the groups don't actually capture any text.
Also, why not just use /([\w\.]+)@([\w\.]+)\.\w+/
? (not too familiar with ruby's regex engine, but that should be about right... you don't even need to check for word boundaries if you're using greedy quantifiers)
Getting each instance of matched string from MatchData
Turns out that simply looping/displaying through each instance of #<MatchData "">
did the trick
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]]
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/)
Matching position in gsub or scan
"hello".gsub(/./) { Regexp.last_match.offset(0).first }
=> "01234"
See Regexp.last_match and MatchData.
Related Topics
Sinatra and Session Variables Which Are Not Being Set
Display Base64 Encoded Image in Rails
How to Rescue Timeout Issues (Ruby, Rails)
File.Open with Block VS Without
Rails: Is Passenger Standalone Suitable for Production Deployment
Dynamically Create Index with Mongoid
Rails Return JSON Serialized Attribute With_Indifferent_Access
Adding a Helper Method with a Gem
How to Ignore or Skip a Test Method Using Rspec
What's the Cleanest Way to Override Activerecord's Find for Both Models and Collections
Difference Between String.Scan and String.Split
What's the Difference Between "=" & "=>" and "@Variable", "@@Variable" and ":Variable" in Ruby
How to Pass an Argument When Calling a View File
Ruby W/ Sinatra: What Is the Equivalent of a .Js.Erb from Rails
Rails Join a List of Strings with Commas and "And" Before the Last
Can't Launch Simple Sinatra App Using Rackup and Jruby (No Response from Web Server)