@growlatoe: "Hi all.
I'm pretty new to Ruby and that sort of thing, and I'm having a few
problems understanding regular expressions. I'm hoping one of you can
point me in the right direction.
I want to replace an entire string with another string. I know you
don't need regular expressions for that, but it's part of a more
generic approach. Anyway, the problem I'm having is that my regular
expressions are finding two matches instead of one, and I don't
understand why. I've narrowed down my confusion to the following code,
which shows some output from irb:
irb(main):001:0> "hello".scan(/.*/)
=> ["hello", ""]
I was expecting one match, not two, because .* matches everything,
right? Can someone explain why an empty string is also matched?
The same thing can be seen when substituting - this is closer to how
I'm using regular expressions in my code:
irb(main):001:0> "hello".gsub(/.*/, "P")
=> "PP"
Two substitutions are made and I expected one. So am I right or wrong
to expect one substitution?
Please help - this is driving me nuts!
And in case it helps...
$ ruby version
ruby 1.8.5 (2006-08-25) [i486-linux]
Thanks in advance."
    @ryemcdonald: "<quote>
I agree. Can someone explain why gsub, sub or scan matches with * are 
different than =~ matches with *
puts "hello".gsub(/[aeiou]/, '<\1>')  # h<>ll<>
puts "hello".gsub(/.*/, '<\1>')       # <><>
print "before: #{$`}\n"               # before: hello
print "match:  #{$&}\n"               # match:
print "after:  #{$'}\n"               # after:
puts "hello" =~ (/.*/)                # 0
print "before: #{$`}\n"               # before:
print "match:  #{$&}\n"               # match:  hello
print "after:  #{$'}\n"               # after:
thanks!
Posted via <url>"
    @Rob: "<quote>
That still doesn't really explain why "hello".scan(/.*/) => ["hello",  
""]
Why wouldn't it be ["hello", "", "", "", "", "", "", "", "", "", "",  
"", ... ] since I (or rather the OP) could continue to match zero  
characters (bytes) at the end of the string forever?  It does seem  
that it might be that a termination condition is checked a bit later  
than it should be in this case.
-Rob
Rob Biedenharn		<url>
<email_address>"
    @lojicdotcom: "<quote>
Why not simply change the 1 to a 0 ?
irb(main):001:0> puts "hello".gsub(/[aeiou]/, '<\0>')
h<e>ll<o>"
    @sdball: "[snip]
<quote>
Ah, but notice:
"hello".scan(/.*$/)
=> ["hello", ""]
"hello".scan(/^.*/)
=> ["hello"]
Strange indeed, but it seems that's how it's working. Although I
suspect I'm not fully grasping the subtleties introduced by the *
character.
Hmm, the more I think on it I think I have an answer:
The /^.*/ pattern specifies that the string must start with anything
(e.g. it must have at least one character) and then zero or more
characters following.
The /.*$/ pattern has no restriction since the anchor is on the side
with the * character. So it's parsed as "zero or more of anything
before the end of the string".
So, if that's correct, you are right that the absence is matched last.
Verified by the fact that the absence follows the string in the
pattern match.
 Stephen"
    @growlatoe: "<quote>
Oh right, I think I get it now. If you try to match anything with *
then a match is guaranteed, because if there's nothing to match, then
you'll just match nothing?
Like this:
irb(main):001:0> "hello".scan(/h*/)
=> ["h", "", "", "", "", ""]
And this:
irb(main):002:0> "hello".scan(/P*/)
=> ["", "", "", "", "", ""]
I've always assumed, and used, .* to make everything before,
but I suppose .+ does make more sense. Although I have to say
I still find it a bit odd...
Thanks everyone for your help."
    @Rob: "<quote>
["hello",
A great example which I *do* consider to be buggy.  The similar =20
example from perl is something like:
$ perl -e '$h =3D "hello"; $h =3D~ s/.*?/[$&]/g; print "$h\n";'
[][h][][e][][l][][l][][o][]
It matches the empty string at the beginning, between each character, =20=
and at the end, but it does consume the actual characters of the =20
string.  Even if not what one would anticipate, it's not too hard to =20
justify the result. (Something that can't be said for ruby's =20
["","","","","",""].)
The other versions from perl are enlightening:
$ perl -e '$h =3D "hello"; $h =3D~ s/.?/[$&]/g; print "$h\n";'
[h][e][l][l][o][]
$ perl -e '$h =3D "hello"; $h =3D~ s/.*/[$&]/g; print "$h\n";'
[hello][]
Both succeed in a zero-character match at the end.  These are =20
equivalent in ruby (1.8.5):
$ ruby -e 'puts "hello".scan(/.?/).inspect'
["h", "e", "l", "l", "o", ""]
$ ruby -e 'puts "hello".scan(/.*/).inspect'
["hello", ""]
I thought I'd see what Oniguruma (5.8.0; with 1.1.0 gem) had to say:
irb> require 'oniguruma'
=3D> true
irb> reluctant =3D Onigurum888a:dbb7:2d49:b3f6:8605:bf4e:caed:e5a4ORegexp.new('.*?')
=3D> /.*?/
irb> greedy =3D Onigurum888a:dbb7:2d49:b3f6:8605:bf4e:caed:e5a4ORegexp.new('.*')
=3D> /.*/
irb> greedyq =3D Onigurum888a:dbb7:2d49:b3f6:8605:bf4e:caed:e5a4ORegexp.new('.?')
=3D> /.?/
irb> reluctant.scan("hello")
=3D> [#<MatchData:0x10b9aa4>, #<MatchData:0x10b9a7c>, #<MatchData:=20
0x10b9a68>, #<MatchData:0x10b9a40>, #<MatchData:0x10b9a18>, =20
#<MatchData:0x10b99f0>]
irb> reluctant.scan("hello").map{|md|md[0]}
=3D> ["", "", "", "", "", ""]
irb> greedy.scan("hello").map{|md|md[0]}
=3D> ["hello", ""]
irb> greedyq.scan("hello").map{|md|md[0]}
=3D> ["h", "e", "l", "l", "o", ""]
OK, the same result as the ruby Regexp.  Including, that .*? produces =20=
[""]*6 which is the "before each character and at the end" locations =20
of the zero-length matches from perl, but the individual single-byte =20
matches are missing.
I presume that there's some justification for these behaviors, but I =20
can't figure out what it might be.
-Rob
I agree that those results are exactly what I'd expect.
Rob Biedenharn		<url>
<email_address>"
    @shortcutter: "<quote>
As far as I remember it works like this: first .* matches the whole 
sequence.  Then the "cursor" is placed behind the match, i.e. after the 
last char of the match and matching starts again.  At this place the 
empty sequence matches because we're at the end of the match.  After 
that match the cursor is advanced one step (to avoid endless 
repetitions) and - alas! - we're at the end of the string and matching 
stops.
For learning regular expressions this is a great program: it allows to 
graphically step through the matching process:
<url>
See also this thread: 
<url>
Btw, for replacing the whole string this is much better:
irb(main):001:0> s = "foo"
=> "foo"
irb(main):002:0> s.object_id
=> 1073540760
irb(main):003:0> s.replace "bar"
=> "bar"
irb(main):004:0> s.object_id
=> 1073540760
irb(main):005:0> s
=> "bar"
irb(main):006:0>
Kind regards
	robert"
    @shortcutter: "<quote>
".*" has its use but it's generally overrated, i.e. more often used than 
needed / wanted.  If you show a more concrete example of what you are 
doing we might be able to come up with better suggestions.  If you are 
really interested to dive into the matter then I suggest "Mastering 
Regular Expressions" which is an excellent book for the money.
Kind regards
	robert"
{'source': 'USENET', 'other_information': '{"reply_count": 8, "forum_name": "comp.lang.ruby.20141126.mbox"}', 'file': 'data/output/usenet-comp.lang.parquet'}