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

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

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

On 7/26/06, Matthew H. [email protected] wrote:

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

[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


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

On Jul 26, 2006, at 6:47 AM, Vincent F. 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 ?

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

James Edward G. II

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

On 7/26/06, Tomas F. [email protected] wrote:


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

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, Guillaume C. [email protected] wrote:

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, Tomas F. [email protected] wrote:

occurence should be replaced.


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®}(?!.*#{Regexp.escape®})},"")

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

On 7/26/06, Robert D. [email protected] wrote:

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

and yet another

Well that is nice :wink:

have
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

    }

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.

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.