Gsub

Hi,

I have a string s= XXaaXX, in which i want to replace the last substring
r, which is determined at run time.

r= XX

s.gsub(/XX\z/,'') solves the problem in a static way.
s.gsub(r,'') solves it too, but who can I specify, that only the last
occurence should be replaced.

Best regards,
Tomas

···

--
Posted via http://www.ruby-forum.com/.

Hello !

s.gsub(/XX\z/,'') solves the problem in a static way.
s.gsub(r,'') solves it too, but who can I specify, that only the last
occurence should be replaced.

  Would
s.gsub(/#{r}$/,'')
  do what you want ?

  Vince

Hi,

thanks for your solutions. But I've forgotten to mention, that r can
contain brackets, so the simple way s.gsub(/#{r}$/,'') doesn't work.

I use now the reverse, sub approach.

Best regards,
Tomas

···

--
Posted via http://www.ruby-forum.com/.

Hi, what you really want to use if you want a clean solution is negative
lookaheads built into your regular expression.

How lookaheads work:

Search google for specific lookahead uses in Ruby as I haven't experienced
them yet with this language.

···

On 7/26/06, Tomas Fischer <tomas_fischer99@yahoo.de> wrote:

Hi,

I have a string s= XXaaXX, in which i want to replace the last substring
r, which is determined at run time.

r= XX

s.gsub(/XX\z/,'') solves the problem in a static way.
s.gsub(r,'') solves it too, but who can I specify, that only the last
occurence should be replaced.

Best regards,
Tomas

--
Posted via http://www.ruby-forum.com/\.

Alternatively you can reverse, sub, reverse, but I like Vince's way.

···

On 7/26/06, Vincent Fourmond <vincent.fourmond@9online.fr> wrote:

Hello !

> s.gsub(/XX\z/,'') solves the problem in a static way.
> s.gsub(r,'') solves it too, but who can I specify, that only the last
> occurence should be replaced.

Would
s.gsub(/#{r}$/,'')
do what you want ?

       Vince

--
Matt

If that's for a single line string, drop the g and just use sub().

James Edward Gray II

···

On Jul 26, 2006, at 6:47 AM, Vincent Fourmond wrote:

  Hello !

s.gsub(/XX\z/,'') solves the problem in a static way.
s.gsub(r,'') solves it too, but who can I specify, that only the last
occurence should be replaced.

  Would
s.gsub(/#{r}$/,'')
  do what you want ?

Well Thomas if your pattern is really at the end of the string you can use
the -- much faster --
anchoring approach Vincent suggested, just escape your regexp and use sub
instead of
gsub as pointed out by Edward in case there is only one line.

s.sub %r{#{Regexp.escape(r)}$}, ""

Robert

···

On 7/26/06, Tomas Fischer <tomas_fischer99@yahoo.de> wrote:

Hi,

thanks for your solutions. But I've forgotten to mention, that r can
contain brackets, so the simple way s.gsub(/#{r}$/,'') doesn't work.

I use now the reverse, sub approach.

Best regards,
Tomas

--
Posted via http://www.ruby-forum.com/\.

Hi, what you really want to use if you want a clean solution is negative
lookaheads built into your regular expression.

How lookaheads work:
Regex Tutorial - Lookahead and Lookbehind Zero-Length Assertions

Search google for specific lookahead uses in Ruby as I haven't experienced
them yet with this language.

Well that is nice :wink:
actually that would be something like

s.sub( %r{#{Regexp.escape(r)}(?!.*#{Regexp.escape(r)})},"")

but I am afraid that this is much more expensive than the
reverse.sub.reverse trick and much less readable

Robert

···

On 7/26/06, Guillaume Carbonneau <gusxedge@gmail.com> wrote:

On 7/26/06, Tomas Fischer <tomas_fischer99@yahoo.de> wrote:

>
> Hi,
>
> I have a string s= XXaaXX, in which i want to replace the last substring
> r, which is determined at run time.
>
> r= XX
>
> s.gsub(/XX\z/,'') solves the problem in a static way.
> s.gsub(r,'') solves it too, but who can I specify, that only the last
> occurence should be replaced.
>
> Best regards,
> Tomas
>
> --
> Posted via http://www.ruby-forum.com/\.
>

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

[SNIP]
OP talked about the last occurence, not an occurence at the end, so
anchoring is not an option :frowning:
reverse sub reverse is a nice idea, I hope you do not mind me spelling it
out

s.reverse.sub(r,"").reverse
and in case U want inline replacement

s.reverse!.sub!(r,"").reverse! # That is rubyish, isn't it :]

Cheers
Robert

···

On 7/26/06, Matthew Harris <shugotenshi@gmail.com> wrote:

Alternatively you can reverse, sub, reverse, but I like Vince's way.

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Sorry about yet another post, but I think this is noteworthy...

Well that is nice :wink:

actually that would be something like

s.sub( %r{#{Regexp.escape(r)}(?!.*#{Regexp.escape(r)})},"")

but I am afraid that this is much more expensive than the
reverse.sub.reverse trick and much less readable

Robert

Variable length lookahead assertions are a killer, just look at this, I have
replaced the last < in this page with ***
that is a string of length 2369, look at the benchmark please:

robert@roma:~/log/ruby/theory/regex$ cat test2.rb && ./test2.rb
#!/usr/bin/env ruby

···

#

require 'benchmark'
string = nil
File.open("gsub.html"){ | file | string = file.read }
s1=s2=nil
r1 = Regexp.new( "<" )
r2 = Regexp.new( "<(?!.*<)", Regexp::MULTILINE )

n = 50000
Benchmark.bm do |x|
      x.report("reverse.sub.reverse") {
        n.times do
                s1 = string.reverse.sub(r1,"***").reverse
        end
        }
      x.report("lookahead") {
        n.times do
                s2 = string.sub(r2,"***")
        end
        }
end
      user system total real
reverse.sub.reverse 1.470000 0.010000 1.480000 ( 1.483691)
lookahead 48.100000 0.060000 48.160000 ( 52.608063)

As far as I know fixed with lookahead is about ok, though.
Cheers
Robert

Sorry about yet another post, but I think this is noteworthy...

and yet another

Well that is nice :wink:

> actually that would be something like
>
> s.sub( %r{#{Regexp.escape(r)}(?!.*#{Regexp.escape(r)})},"")
>
> but I am afraid that this is much more expensive than the
> reverse.sub.reverse trick and much less readable
>
> Robert
>
Variable length lookahead assertions are a killer, just look at this, I
have
replaced the last < in this page with ***
that is a string of length 2369, look at the benchmark please:

robert@roma:~/log/ruby/theory/regex$ cat test2.rb && ./test2.rb
#!/usr/bin/env ruby
#

require 'benchmark'
string = nil
File.open("gsub.html"){ | file | string = file.read }
s1=s2=nil
r1 = Regexp.new( "<" )
r2 = Regexp.new( "<(?!.*<)", Regexp::MULTILINE )

that is stupid
use non greedy
r2 = Regexp.new( "<(?!.*?<)", Regexp::MULTILINE )

n = 50000

Benchmark.bm do |x|
      x.report("reverse.sub.reverse") {
        n.times do
                s1 = string.reverse.sub(r1,"***").reverse
        end
        }
      x.report("lookahead") {
        n.times do
                s2 = string.sub(r2,"***")
        end
        }
end
      user system total real
reverse.sub.reverse 1.470000 0.010000 1.480000 ( 1.483691)
lookahead 48.100000 0.060000 48.160000 ( 52.608063)

better but not god enough
generous lookahead 14.900000 0.010000 14.910000 ( 15.481074)

As far as I know fixed with lookahead is about ok, though.

···

On 7/26/06, Robert Dober <robert.dober@gmail.com> wrote:

Cheers
Robert