<p>Is there a quick way to find every match of a regular expression in Ruby? I've looked through the Regex object in the Ruby STL and searched on Google to no avail.</p>

[{'answer_id': 80387, 'author': 'Jean', 'author_id': 7898, 'author_profile': 'https://Stackoverflow.com/users/7898', 'pm_score': 11, 'selected': True, 'text': '<p>Using <a href="http://ruby-doc.org/core-1.9.3/String.html#method-i-scan" rel="noreferrer"><code>scan</code></a> should do the trick:</p>\n\n<pre><code>string.scan(/regex/)\n</code></pre>\n'}, {'answer_id': 35964234, 'author': 'sudo bangbang', 'author_id': 3951782, 'author_profile': 'https://Stackoverflow.com/users/3951782', 'pm_score': 6, 'selected': False, 'text': '<p>To find all the matching strings, use String\'s <a href="http://ruby-doc.org/core-2.2.0/String.html#method-i-scan" rel="noreferrer"><code>scan</code></a> method.</p>\n\n<pre><code>str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"\nstr.scan(/\\d+/)\n#=&gt; ["54", "3", "1", "7", "3", "36", "0"]\n</code></pre>\n\n<p>If you want, <a href="http://ruby-doc.org/core-1.9.3/MatchData.html" rel="noreferrer"><code>MatchData</code></a>, which is the type of the object returned by the Regexp <code>match</code> method, use:</p>\n\n<pre><code>str.to_enum(:scan, /\\d+/).map { Regexp.last_match }\n#=&gt; [#&lt;MatchData "54"&gt;, #&lt;MatchData "3"&gt;, #&lt;MatchData "1"&gt;, #&lt;MatchData "7"&gt;, #&lt;MatchData "3"&gt;, #&lt;MatchData "36"&gt;, #&lt;MatchData "0"&gt;]\n</code></pre>\n\n<p>The benefit of using <code>MatchData</code> is that you can use methods like <code>offset</code>:</p>\n\n<pre><code>match_datas = str.to_enum(:scan, /\\d+/).map { Regexp.last_match }\nmatch_datas[0].offset(0)\n#=&gt; [2, 4]\nmatch_datas[1].offset(0)\n#=&gt; [7, 8]\n</code></pre>\n\n<p>See these questions if you\'d like to know more:</p>\n\n<ul>\n<li>"<a href="https://stackoverflow.com/questions/6804557/how-do-i-get-the-match-data-for-all-occurrences-of-a-ruby-regular-expression-in?lq=1">How do I get the match data for all occurrences of a Ruby regular expression in a string?</a>"</li>\n<li>"<a href="https://stackoverflow.com/questions/19596382/ruby-regular-expression-matching-enumerator-with-named-capture-support?lq=1">Ruby regular expression matching enumerator with named capture support</a>"</li>\n<li>"<a href="https://stackoverflow.com/questions/17185943/how-to-find-out-the-starting-point-for-each-match-in-ruby?lq=1">How to find out the starting point for each match in ruby</a>"</li>\n</ul>\n\n<p>Reading about special variables <code>$&amp;</code>, <code>$\'</code>, <code>$1</code>, <code>$2</code> in Ruby will be helpful too.</p>\n'}, {'answer_id': 36751235, 'author': 'MVP', 'author_id': 6231595, 'author_profile': 'https://Stackoverflow.com/users/6231595', 'pm_score': 4, 'selected': False, 'text': '<p>if you have a regexp with groups:</p>\n\n<pre><code>str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"\nre=/(\\d+)[m-t]/\n</code></pre>\n\n<p>you can use String\'s <code>scan</code> method to find matching groups:</p>\n\n<pre><code>str.scan re\n#&gt; [["54"], ["1"], ["3"]]\n</code></pre>\n\n<p>To find the matching pattern:</p>\n\n<pre><code>str.to_enum(:scan,re).map {$&amp;}\n#&gt; ["54m", "1t", "3r"]\n</code></pre>\n'}, {'answer_id': 60586543, 'author': 'Datt', 'author_id': 1398515, 'author_profile': 'https://Stackoverflow.com/users/1398515', 'pm_score': 3, 'selected': False, 'text': '<p>You can use <code>string.scan(your_regex).flatten</code>. If your regex contains groups, it will return in a single plain array. </p>\n\n<pre><code>string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"\nyour_regex = /(\\d+)[m-t]/\nstring.scan(your_regex).flatten\n=&gt; ["54", "1", "3"]\n</code></pre>\n\n<p>Regex can be a named group as well.</p>\n\n<pre><code>string = \'group_photo.jpg\'\nregex = /\\A(?&lt;name&gt;.*)\\.(?&lt;ext&gt;.*)\\z/\nstring.scan(regex).flatten\n</code></pre>\n\n<p>You can also use <code>gsub</code>, it\'s just one more way if you want MatchData.</p>\n\n<pre><code>str.gsub(/\\d/).map{ Regexp.last_match }\n</code></pre>\n'}, {'answer_id': 72266342, 'author': 'Victor', 'author_id': 7644846, 'author_profile': 'https://Stackoverflow.com/users/7644846', 'pm_score': 0, 'selected': False, 'text': '<p>If you have capture groups <code>()</code> inside the regex for other purposes, the proposed solutions with <code>String#scan</code> and <code>String#match</code> are problematic:</p>\n<ol>\n<li><code>String#scan</code> only get what is inside the <a href="https://docs.ruby-lang.org/en/2.4.0/syntax/refinements_rdoc.html" rel="nofollow noreferrer">capture groups</a>;</li>\n<li><code>String#match</code> only get the first match, rejecting all the others;</li>\n<li><code>String#matches</code> (proposed function) get all the matches.</li>\n</ol>\n<p>On this case, we need a solution to match the regex without considering the capture groups.</p>\n<h1><code>String#matches</code></h1>\n<p>With the <a href="https://docs.ruby-lang.org/en/2.4.0/syntax/refinements_rdoc.html" rel="nofollow noreferrer">Refinements</a> you can monkey patch the <code>String</code> class, implement the <code>String#matches</code> and this method will be available inside the scope of the class that is using the refinement. It is an incredible way to Monkey Patch classes on Ruby.</p>\n<h3>Setup</h3>\n<ul>\n<li><code>/lib/refinements/string_matches.rb</code></li>\n</ul>\n<pre class="lang-rb prettyprint-override"><code># This module add a String refinement to enable multiple String#match()s\n# 1. `String#scan` only get what is inside the capture groups (inside the parens)\n# 2. `String#match` only get the first match\n# 3. `String#matches` (proposed function) get all the matches\nmodule StringMatches\n  refine String do\n    def matches(regex)\n      scan(/(?&lt;matching&gt;#{regex})/).flatten\n    end\n  end\nend\n\n</code></pre>\n<p>Used: <a href="https://ruby-doc.org/core-2.4.3/Regexp.html" rel="nofollow noreferrer">named capture groups</a></p>\n<h3>Usage</h3>\n<ul>\n<li><code>rails c</code></li>\n</ul>\n<pre class="lang-rb prettyprint-override"><code>&gt; require \'refinements/string_matches\'\n\n&gt; using StringMatches\n\n&gt; \'function(1, 2, 3) + function(4, 5, 6)\'.matches(/function\\((\\d), (\\d), (\\d)\\)/)\n=&gt; [&quot;function(1, 2, 3)&quot;, &quot;function(4, 5, 6)&quot;]\n\n&gt; \'function(1, 2, 3) + function(4, 5, 6)\'.scan(/function\\((\\d), (\\d), (\\d)\\)/)\n=&gt; [[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;], [&quot;4&quot;, &quot;5&quot;, &quot;6&quot;]]\n\n&gt; \'function(1, 2, 3) + function(4, 5, 6)\'.match(/function\\((\\d), (\\d), (\\d)\\)/)[0]\n=&gt; &quot;function(1, 2, 3)&quot;\n</code></pre>\n'}, {'answer_id': 73542998, 'author': 'some_guy', 'author_id': 4019925, 'author_profile': 'https://Stackoverflow.com/users/4019925', 'pm_score': -1, 'selected': False, 'text': "<h1>Return an array of <code>MatchData</code> objects</h1>\n<p><code>#scan</code> is very limited--only returns a simple array of strings!</p>\n<p>Far more powerful/flexible for us to get an array of <code>MatchData</code> objects.</p>\n<p>I'll provide two approaches (using same logic), one using a PORO and one using a monkey patch:</p>\n<h2>PORO:</h2>\n<pre><code>class MatchAll\n  def initialize(string, pattern)\n    raise ArgumentError, 'must pass a String' unless string.is_a?(String)\n\n    raise ArgumentError, 'must pass a Regexp pattern' unless pattern.is_a?(Regexp)\n\n    @string = string\n    @pattern = pattern\n    @matches = []\n  end\n\n  def match_all\n    recursive_match\n  end\n\n  private\n\n  def recursive_match(prev_match = nil)\n    index = prev_match.nil? ? 0 : prev_match.offset(0)[1]\n\n    matching_item = @string.match(@pattern, index)\n    return @matches unless matching_item.present?\n\n    @matches &lt;&lt; matching_item\n    recursive_match(matching_item)\n  end\nend\n</code></pre>\n<p><strong>USAGE:</strong></p>\n<pre><code>test_string = 'a green frog jumped on a green lilypad'\n\nMatchAll.new(test_string, /green/).match_all\n=&gt; [#&lt;MatchData &quot;green&quot;, #&lt;MatchData &quot;green&quot;]\n</code></pre>\n<hr />\n<h2>Monkey patch</h2>\n<p>I don't typically condone monkey-patching, but in this case:</p>\n<ul>\n<li>we're doing it the right way by &quot;quarantining&quot; our patch into its own module</li>\n<li>I prefer this approach because <code>'string'.match_all(/pattern/)</code> is more intuitive (and looks a lot nicer) than <code>MatchAll.new('string', /pattern/).match_all</code></li>\n</ul>\n<pre><code>module RubyCoreExtensions\n  module String\n    module MatchAll\n      def match_all(pattern)\n        raise ArgumentError, 'must pass a Regexp pattern' unless pattern.is_a?(Regexp)\n\n        recursive_match(pattern)\n      end\n\n      private\n\n      def recursive_match(pattern, matches = [], prev_match = nil)\n        index = prev_match.nil? ? 0 : prev_match.offset(0)[1]\n\n        matching_item = self.match(pattern, index)\n        return matches unless matching_item.present?\n\n        matches &lt;&lt; matching_item\n        recursive_match(pattern, matches, matching_item)\n      end\n    end\n  end\nend\n\n</code></pre>\n<p>I recommend creating a new file and putting the patch (assuming you're using Rails) there <code>/lib/ruby_core_extensions/string/match_all.rb</code></p>\n<p>To use our patch we need to make it available:</p>\n<pre><code># within application.rb\nrequire './lib/ruby_core_extensions/string/match_all.rb'\n</code></pre>\n<p>Then be sure to include it in the <code>String</code> class (you could put this wherever you want; but for example, right under the require statement we just wrote above. After you <code>include</code> it once, it will be available everywhere, even outside the class where you included it).</p>\n<pre><code>String.include RubyCoreExtensions::String::MatchAll\n</code></pre>\n<p><strong>USAGE: And now when you use <code>#match_all</code> you get results like:</strong></p>\n<pre><code>test_string = 'hello foo, what foo are you going to foo today?'\n\ntest_string.match_all /foo/\n=&gt; [#&lt;MatchData &quot;foo&quot;, #&lt;MatchData &quot;foo&quot;, #&lt;MatchData &quot;foo&quot;]\n\ntest_string.match_all /hello/\n=&gt; [#&lt;MatchData &quot;hello&quot;]\n\ntest_string.match_all /none/\n=&gt; []\n</code></pre>\n<hr />\n<p>I find this particularly useful when I want to match multiple occurrences, and then get useful information about each occurrence, such as which index the occurrence starts and ends (e.g. <code>match.offset(0) =&gt; [first_index, last_index]</code>)</p>\n"}]
['https://Stackoverflow.com/questions/80357', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/422/']