From: Robert Klemme Date: 2004-01-21T02:20:04+09:00 Subject: Re: regex help ------=_NextPart_000_001F_01C3DF81.D295E540 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit "Nikolai Weibull" schrieb im Newsbeitrag news:20040120165640.GB1987@puritan.bredbandsbolaget.se... > * Robert Klemme [Jan, 20 2004 17:30]: > > > str.gsub!(/"[^"\\]*(\\.[^"\\]*)*"|\*\//){ |m| m == '\*' ? '*\\' : m } > > Did you test that? I'm afraid, it doesn't work: > yes, but i seem to have made a mistake in copying it over for some > reason, the problem is the test, not the regex, it should be > > str.gsub!(/"[^"\\]*(\\.[^"\\]*)*"|\*\//){ |m| m == '*/' ? '*\\' : m } > ^^ Oops, yes you're right. > > If you want to allow quotes to be escaped, this one is the way to go: > > > > irb(main):012:0> puts str.gsub(%r{"([^"\\]|\\")*"|\*/}) {|m| m == '*/' ? > > '*\\' : m} > > /* comment *\ String s = "***/"; > well, this isn't really correct, that would only escape quotes and you > wouldn't allow for escaped backslashes in your strings....it is of > course trivial to mend. do note that my version is a lot faster...see > "Mastering Regular Expressions" by Jeffrey E. F. Friedl on why this is > so. anyway, thanks for pointing out that something was wrong, > nikolai I've added escaping of arbitrary chars and put it into a benchmark (attached). The differences don't look too big: 18:07:21 [ruby]: ./rx-bm.rb user system total real mine 1.781000 0.000000 1.781000 ( 1.776000) yours 1.719000 0.000000 1.719000 ( 1.732000) 18:07:26 [ruby]: ./rx-bm.rb user system total real mine 1.781000 0.000000 1.781000 ( 1.785000) yours 1.704000 0.000000 1.704000 ( 1.712000) 18:07:31 [ruby]: ./rx-bm.rb user system total real mine 1.781000 0.000000 1.781000 ( 1.800000) yours 1.719000 0.000000 1.719000 ( 1.706000) 18:07:36 [ruby]: ./rx-bm.rb user system total real mine 1.781000 0.000000 1.781000 ( 1.788000) yours 1.703000 0.000000 1.703000 ( 1.693000) 18:07:43 [ruby]: ./rx-bm.rb user system total real mine 1.766000 0.000000 1.766000 ( 1.788000) yours 1.719000 0.000000 1.719000 ( 1.707000) 18:07:52 [ruby]: That's certainly not what I'd call "a lot faster". Maybe the effects of GC dominate the rx timing. Here's the output of the second benchmark: 18:15:22 [ruby]: ./rx-bm-2.rb user system total real mine 3.234000 0.000000 3.234000 ( 3.227000) yours 3.157000 0.016000 3.173000 ( 3.188000) 18:15:33 [ruby]: ./rx-bm-2.rb user system total real mine 3.203000 0.000000 3.203000 ( 3.218000) yours 3.125000 0.016000 3.141000 ( 3.231000) 18:15:44 [ruby]: ./rx-bm-2.rb user system total real mine 3.187000 0.000000 3.187000 ( 3.257000) yours 3.156000 0.000000 3.156000 ( 3.186000) Doesn't look so much different. Any ideas or enlightening comments from the aforementioned book? Kind regards robert ------=_NextPart_000_001F_01C3DF81.D295E540 Content-Type: application/octet-stream; name="rx-bm.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="rx-bm.rb" #!/usr/bin/ruby require 'benchmark' include Benchmark N=3D100000 str =3D ' /* comment */ String s =3D "***/"; ' bm do |x| x.report("mine") do for n in 1..N str.gsub(%r{"([^"\\]|\\.)*"|\*/}) {|m| m =3D=3D '*/' ? '*\\' : m} end end x.report("yours") do for n in 1..N str.gsub(/"[^"\\]*(\\.[^"\\]*)*"|\*\//){ |m| m =3D=3D '*/' ? '*\\' = : m } end end end ------=_NextPart_000_001F_01C3DF81.D295E540 Content-Type: application/octet-stream; name="rx-bm-2.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="rx-bm-2.rb" #!/usr/bin/ruby require 'benchmark' include Benchmark N=3D100000 str =3D ' /* comment */ String s =3D "***/"; ' a_mine =3D (1..N).map{str.dup} a_yours =3D (1..N).map{str.dup} bm do |x| x.report("mine") do a_mine.each do |str| str.gsub!(%r{"([^"\\]|\\.)*"|\*/}) {|m| m =3D=3D '*/' ? '*\\' : m} end end x.report("yours") do a_yours.each do |str| str.gsub!(/"[^"\\]*(\\.[^"\\]*)*"|\*\//){ |m| m =3D=3D '*/' ? = '*\\' : m } end end end ------=_NextPart_000_001F_01C3DF81.D295E540--