From 2e47789634a46aab0f591a987beaedb7bfbbdd5e Mon Sep 17 00:00:00 2001 From: root Date: Sat, 10 Aug 2013 11:19:40 +0000 Subject: [PATCH 1/2] added finding all matches page --- .../finding-all-matches.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 chapters/regular_expressions/finding-all-matches.md diff --git a/chapters/regular_expressions/finding-all-matches.md b/chapters/regular_expressions/finding-all-matches.md new file mode 100644 index 0000000..db2921b --- /dev/null +++ b/chapters/regular_expressions/finding-all-matches.md @@ -0,0 +1,37 @@ +--- +layout: recipe +title: Finding All Matches +chapter: Regular Expressions +--- +## Problem + +You need to find all matches, not just the first. + +## Solution + +{% highlight coffeescript %} +RegExp::execAll = (haystack) -> + return [] unless @global + match[0] while match = @exec haystack + +text = "I have 4 dogs, 7 cats, and 42 gold fish." +/d+/g.execAll text +# => ["4", "7", "42"] +{% endhighlight %} + +## Discussion + +The above throws away submatches, in order to simplify the result. You can keep them with this variant. + +{% highlight coffeescript %} +RegExp::execAll = (haystack) -> + return [] unless @global + match while match = @exec haystack + +/(\d+) (\w+)/g.execAll "I have 4 dogs, 7 cats, and 42 gold fish." +# => [["4 dogs","4","dogs"],["7 cats","7","cats"],["42 gold","42","gold"]] +{% endhighlight %} + +The first line of `execAll` prevents an infinite loop caused by non-global expressions. This could be further improved by creating a clone of the RegExp that is global, and use that. + + From 4e3c08aab7d223ed8338585c3518b09d9477185a Mon Sep 17 00:00:00 2001 From: Frankie Bagnardi Date: Mon, 12 Aug 2013 16:40:15 -0700 Subject: [PATCH 2/2] added more detail to regex match all, and problem clarified --- .../finding-all-matches.md | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/chapters/regular_expressions/finding-all-matches.md b/chapters/regular_expressions/finding-all-matches.md index db2921b..cc18ad8 100644 --- a/chapters/regular_expressions/finding-all-matches.md +++ b/chapters/regular_expressions/finding-all-matches.md @@ -7,6 +7,13 @@ chapter: Regular Expressions You need to find all matches, not just the first. +For example, + +{% highlight coffeescript %} +/\d+/g.exec "I have 4 dogs, 7 cats, and 42 gold fish." +# => ["4"] +{% endhighlight %} + ## Solution {% highlight coffeescript %} @@ -32,6 +39,29 @@ RegExp::execAll = (haystack) -> # => [["4 dogs","4","dogs"],["7 cats","7","cats"],["42 gold","42","gold"]] {% endhighlight %} -The first line of `execAll` prevents an infinite loop caused by non-global expressions. This could be further improved by creating a clone of the RegExp that is global, and use that. +The first line of `execAll` prevents an infinite loop caused by non-global expressions. This could be further +improved by creating a clone of the RegExp that is global, and use that. +You must not save a reference to this expression (like `a = /xyx/g`) if you plan to call `execAll` more than once. +The same behavior be observed with the regular `exec` method. + +{% highlight coffeescript %} +s = "I have 4 dogs, 7 cats, and 42 gold fish." +myRegEx = /\d+/g +myRegEx.exec s +# => ["4"] +myRegEx.execAll s +# => ["7", "42"] +myRegEx.exec s +# => null +{% endhighlight %} + +Instead use: + +{% highlight coffeescript %} +/\d+/g.execAll s +# => ["4", "7", "42"] +/\d+/g.execAll s +# => ["4", "7", "42"] +{% endhighlight %}