# \[Q\] difference between StringScanner#scan and Regexp#match

**URL:** <https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724>\
**Category:** ruby-talk\
**Created:** [24 February 2008 04:20 UTC](https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724 "2008-02-24T04:20:08Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Makoto\_Kuwata](https://avatars.discourse-cdn.com/v4/letter/m/a4c791/32.png) [@Makoto\_Kuwata](https://rubytalk.org/u/Makoto_Kuwata)\
**Post date:** [24 February 2008 04:20 UTC](https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724/1 "2008-02-24T04:20:08Z")

</div>

Hi,

I'm planning to implement StringScanner in pure Ruby.  
But I found that it is hard to implement StringScanner#scan()  
in pure Ruby, because of the difference between Regexp#match()  
and StringScanner#scan().

StringScanner#scan() matches only when pattern matches at the  
beginning (or at the current position) of input string.

&nbsp;&nbsp;require 'strscan'  
&nbsp;&nbsp;input = 'foo 123'  
&nbsp;&nbsp;scanner = StringScanner.new(input)  
&nbsp;&nbsp;p scanner.scan(/\d+/) #=\> nil

But Regexp#match() matches whenever input string contains pattern.

&nbsp;&nbsp;input = 'foo 123'  
&nbsp;&nbsp;m = /\d+/.match(input)  
&nbsp;&nbsp;p m[0] if m #=\> "123"

Is it possible to restrict Regexp#match() to match only when  
pattern starts at the beginning of input string?  
My idea is to convert /regexp/ into /\A(?:regexp)/ every time,  
but it is a litte ugly.  
Is there any good idea to emulate StringScanner#scan in pure Ruby?

> **···**
>
> --  
> regards,  
> makoto kuwata

---

<div class="post-metadata">

**Author:** ![Michael\_Fellinger1](https://avatars.discourse-cdn.com/v4/letter/m/e47774/32.png) [@Michael\_Fellinger1](https://rubytalk.org/u/Michael_Fellinger1)\
**Post date:** [24 February 2008 05:33 UTC](https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724/2 "2008-02-24T05:33:58Z")

</div>

input = 'foo 123'  
if (input =~ /\d+/) == 0  
&nbsp;&nbsp;p $& # doesn't happen  
end

> **···**
>
> On Sun, Feb 24, 2008 at 1:20 PM, makoto kuwata \<kwa@kuwata-lab.com\> wrote:
> 
> > Hi,
> > 
> > I'm planning to implement StringScanner in pure Ruby.  
> > But I found that it is hard to implement StringScanner#scan()  
> > in pure Ruby, because of the difference between Regexp#match()  
> > and StringScanner#scan().
> > 
> > StringScanner#scan() matches only when pattern matches at the  
> > beginning (or at the current position) of input string.
> > 
> > &nbsp;&nbsp;require 'strscan'  
> > &nbsp;&nbsp;input = 'foo 123'  
> > &nbsp;&nbsp;scanner = StringScanner.new(input)  
> > &nbsp;&nbsp;p scanner.scan(/\d+/) #=\> nil
> > 
> > But Regexp#match() matches whenever input string contains pattern.
> > 
> > &nbsp;&nbsp;input = 'foo 123'  
> > &nbsp;&nbsp;m = /\d+/.match(input)  
> > &nbsp;&nbsp;p m[0] if m #=\> "123"
> > 
> > Is it possible to restrict Regexp#match() to match only when  
> > pattern starts at the beginning of input string?  
> > My idea is to convert /regexp/ into /\A(?:regexp)/ every time,  
> > but it is a litte ugly.  
> > Is there any good idea to emulate StringScanner#scan in pure Ruby?

---

<div class="post-metadata">

**Author:** ![Caleb\_Clausen1](https://avatars.discourse-cdn.com/v4/letter/c/8dc957/32.png) [@Caleb\_Clausen1](https://rubytalk.org/u/Caleb_Clausen1)\
**Post date:** [25 February 2008 22:12 UTC](https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724/3 "2008-02-25T22:12:10Z")

</div>

I've done this kind of thing before, and rewriting the regex was the  
best I could come up with. If Michael's suggestion is too slow for  
you, then regex rewriting is the only game in town. (Actually, if you  
can determine that your regexes always require some leading substring,  
you might be able to optimize Michael's way a bit more...)

If speed is an issue, why not just use the existing StringScanner?  
Creating regex's at runtime can cost you quite a bit in performance as  
well... some caching can help here, if the same regexes are likely to  
be encountered again.

You might want to take a look at String#index (and it's 2nd parameter)  
rather than String#match or Regexp#match, as it allows you to start  
matching wherever you want in the string, rather than just the  
beginning. That doesn't help with your immediate question, but maybe  
it'll give you some ideas of different ways to approach it.

Finally, a moment of self-promotion. My library 'sequence' implements  
basically what you want (using regex rewriting, which in the full  
elaboration gets rather involved). Maybe it could save you some  
effort...

> **···**
>
> On 2/23/08, makoto kuwata \<kwa@kuwata-lab.com\> wrote:
> 
> > Hi,
> > 
> > I'm planning to implement StringScanner in pure Ruby.  
> > But I found that it is hard to implement StringScanner#scan()  
> > in pure Ruby, because of the difference between Regexp#match()  
> > and StringScanner#scan().
> > 
> > StringScanner#scan() matches only when pattern matches at the  
> > beginning (or at the current position) of input string.
> > 
> > require 'strscan'  
> > input = 'foo 123'  
> > scanner = StringScanner.new(input)  
> > p scanner.scan(/\d+/) #=\> nil
> > 
> > But Regexp#match() matches whenever input string contains pattern.
> > 
> > input = 'foo 123'  
> > m = /\d+/.match(input)  
> > p m[0] if m #=\> "123"
> > 
> > Is it possible to restrict Regexp#match() to match only when  
> > pattern starts at the beginning of input string?  
> > My idea is to convert /regexp/ into /\A(?:regexp)/ every time,  
> > but it is a litte ugly.  
> > Is there any good idea to emulate StringScanner#scan in pure Ruby?

---

<div class="post-metadata">

**Author:** ![Makoto\_Kuwata](https://avatars.discourse-cdn.com/v4/letter/m/a4c791/32.png) [@Makoto\_Kuwata](https://rubytalk.org/u/Makoto_Kuwata)\
**Post date:** [24 February 2008 07:44 UTC](https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724/4 "2008-02-24T07:44:56Z")

</div>

thank you Michael, but it is slow and not efficient, especially input  
string is long, I think.

> **···**
>
> Michael Fellinger \<m.fellin...@gmail.com\> wrote:
> 
> > input = 'foo 123'  
> > if (input =~ /\d+/) == 0  
> > p $& # doesn't happen  
> > end
> 
> --  
> regards,  
> makoto kuwata

---

<div class="post-metadata">

**Author:** ![Michael\_Fellinger1](https://avatars.discourse-cdn.com/v4/letter/m/e47774/32.png) [@Michael\_Fellinger1](https://rubytalk.org/u/Michael_Fellinger1)\
**Post date:** [26 February 2008 04:00 UTC](https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724/5 "2008-02-26T04:00:51Z")

</div>

> \> Hi,  
> \>  
> \> I'm planning to implement StringScanner in pure Ruby.  
> \> But I found that it is hard to implement StringScanner#scan()  
> \> in pure Ruby, because of the difference between Regexp#match()  
> \> and StringScanner#scan().  
> \>  
> \> StringScanner#scan() matches only when pattern matches at the  
> \> beginning (or at the current position) of input string.  
> \>  
> \> require 'strscan'  
> \> input = 'foo 123'  
> \> scanner = StringScanner.new(input)  
> \> p scanner.scan(/\d+/) #=\> nil  
> \>  
> \> But Regexp#match() matches whenever input string contains pattern.  
> \>  
> \> input = 'foo 123'  
> \> m = /\d+/.match(input)  
> \> p m[0] if m #=\> "123"  
> \>  
> \>  
> \> Is it possible to restrict Regexp#match() to match only when  
> \> pattern starts at the beginning of input string?  
> \> My idea is to convert /regexp/ into /\A(?:regexp)/ every time,  
> \> but it is a litte ugly.  
> \> Is there any good idea to emulate StringScanner#scan in pure Ruby?
> 
> I've done this kind of thing before, and rewriting the regex was the  
> best I could come up with. If Michael's suggestion is too slow for  
> you, then regex rewriting is the only game in town. (Actually, if you  
> can determine that your regexes always require some leading substring,  
> you might be able to optimize Michael's way a bit more...)
> 
> If speed is an issue, why not just use the existing StringScanner?  
> Creating regex's at runtime can cost you quite a bit in performance as  
> well... some caching can help here, if the same regexes are likely to  
> be encountered again.

I, for one, started to work on a StringScanner replacement as well  
just for fun. But it could be useful for rubinius to have a pure Ruby  
implementation that can be augmented with C in some core areas by a  
simple require.

> You might want to take a look at String#index (and it's 2nd parameter)  
> rather than String#match or Regexp#match, as it allows you to start  
> matching wherever you want in the string, rather than just the  
> beginning. That doesn't help with your immediate question, but maybe  
> it'll give you some ideas of different ways to approach it.
> 
> Finally, a moment of self-promotion. My library 'sequence' implements  
> basically what you want (using regex rewriting, which in the full  
> elaboration gets rather involved). Maybe it could save you some  
> effort...

Thanks for the hint: [http://sequence.rubyforge.org](http://sequence.rubyforge.org) for anyone who is  
too lazy to type it 🙂

^ manveru

> **···**
>
> On Tue, Feb 26, 2008 at 7:12 AM, Caleb Clausen \<vikkous@gmail.com\> wrote:
> 
> > On 2/23/08, makoto kuwata \<kwa@kuwata-lab.com\> wrote:

---

<div class="post-metadata">

**Author:** ![Michael\_Fellinger1](https://avatars.discourse-cdn.com/v4/letter/m/e47774/32.png) [@Michael\_Fellinger1](https://rubytalk.org/u/Michael_Fellinger1)\
**Post date:** [24 February 2008 09:21 UTC](https://rubytalk.org/t/q-difference-between-stringscanner-scan-and-regexp-match/44724/6 "2008-02-24T09:21:35Z")

</div>

> \> input = 'foo 123'  
> \> if (input =~ /\d+/) == 0  
> \> p $& # doesn't happen  
> \> end
> 
> thank you Michael, but it is slow and not efficient, especially input  
> string is long, I think.

You are right of course, but i don't know any other way, =~ is about  
as fast as you can get already without modifying the regular  
expression.

> **···**
>
> On Sun, Feb 24, 2008 at 4:44 PM, makoto kuwata \<kwa@kuwata-lab.com\> wrote:
> 
> > Michael Fellinger \<m.fellin...@gmail.com\> wrote:
> 
> > --  
> > regards,  
> > makoto kuwata
