Why gsub! doesn't work in my script

Hi all,

I want to search one pattern in a file line by line and replace it with
new pattern one. But it doesn’t work. I cannot change the old pattern
into the new one using gsub! Is there any problem with my script?

Thanks,

Li

################Ruby script##############

#create a regular expression and its replacement

r1_obj=Regexp.escape(‘1.000000$P1G\1.000000’) #pattern
r2_obj=Regexp.escape(‘2.000000$P1G\2.000000’) #replacement

DATA.each_line do |line|
if line.match(r1_obj)
line.gsub!(r1_obj, r2_obj) #
puts line
end
end

END

test1.001
K:\flow\test\test1.001
xxx\1.000000$P1G\1.000000\xxx
yyyy\1.000000$P1G\1.000000\xxx
test1.002
K:\flow\test\test1.002
xxx\1.000000$P1G\1.000000\xxx
yyyy\1.000000$P1G\1.000000\xxx
test1.003
K:\flow\test\test1.003
xxx\1.000000$P1G\1.000000\xxx
yyyy\1.000000$P1G\1.000000\xxx

####screen output###########

xxx\1.000000$P1G\1.000000\xxx
yyyy\1.000000$P1G\1.000000\xxx
xxx\1.000000$P1G\1.000000\xxx
yyyy\1.000000$P1G\1.000000\xxx
xxx\1.000000$P1G\1.000000\xxx
yyyy\1.000000$P1G\1.000000\xxx

Backslash ( \ ) is the escape character. If you want to match \ itself,
you
need to escape it ( \ ). So try these regex’s:

r1_obj=Regexp.escape(‘1.000000\$P1G\1.000000’) #pattern
r2_obj=Regexp.escape(‘2.000000\$P1G\2.000000’) #replacement

Jason

Jason R. wrote:

Backslash ( \ ) is the escape character. If you want to match \ itself,
you
need to escape it ( \ ). So try these regex’s:

r1_obj=Regexp.escape(‘1.000000\$P1G\1.000000’) #pattern
r2_obj=Regexp.escape(‘2.000000\$P1G\2.000000’) #replacement

Jason

Thanks, but the replacement still doesn’t work.

It is my understanding that Regexp#escape method should do the magic
work for me.

Li

On Mon, 11 Jun 2007 22:34:16 +0900, Li Chen wrote:

DATA.each_line do |line|
if line.match(r1_obj)
line.gsub!(r1_obj, r2_obj) #
puts line
end
end

Regexp.escape takes a string as a parameter, and returns a string as its
return value. When you use that string in your Regexp.escape call, you
convert it into something that no longer matches the text in your file,
and when you use the returned string in the gsub call, it tries to match
it literally.

irb(main):003:0> “…”.gsub(Regexp.escape("."),“x”)
=> “…”
irb(main):004:0> “…”.gsub(".",“x”)
=> “xxx”
irb(main):005:0> “…”.gsub(Regexp.new(Regexp.escape(".")),“x”)
=> “xxx”

In message [email protected], Li Chen
writes:

Thanks, but the replacement still doesn’t work.

It is my understanding that Regexp#escape method should do the magic
work for me.

Your understanding makes no sense.

When you put a backslash in a string, it is eaten up by the interpreter
BEFORE ANY METHODS ARE ACTUALLY CALLED. Regexp#escape gets the string
AFTER backslashes have been eaten.

So there’s nothing there for it to escape. The escape method isn’t
magic; it can’t tell how your source is laid out, only what actual
string
it is given.

-s

On Jun 11, 10:49 am, Li Chen [email protected] wrote:

  1. I modify my codes and I get the expected results. But the odd is that
    I have to use 3 backslashes before the 2nd 2. How to explain this.

This is because the 2nd string can use \1, \2, etc… as a replacement
for a previous match in the 1st string (matches are specified in the
1st string in parentheses). This topic was discussed here a few days
ago:

http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/78325335e89ce302/c99e5dda10c017fb#c99e5dda10c017fb

On 6/11/07, Li Chen [email protected] wrote:

DATA.each_line do |line|

      if line=~/1\.000000\\\$P1G\\1\.000000/
           line.gsub!(/1\.000000\\\$P1G\\1\.000000/,

‘2.000000\$P1G\\2.000000’)
puts line
end
end

How about this:

In single quoted strings you only escape \ and ’

You can interpolate into a pattern literal.

pat = /#{Regexp.escape(‘1.000000$P1G\1.000000’)}/

No need for Regexp.escape here since the second parameter to gsub!

is a string, not a pattern.

sub = ‘2.000000\$P1G\2.000000’)

And then either:

if line =~ pat
line.gsub!(pat,sub)
puts line
end

or just

puts line if line.gsub!(pat,sub)

since gsub! returns nil if no substitution was performed and the
string if it was.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Rick,

Thank you very much. Your codes are the simplest and most concise for
me.

Li

On Tue, 12 Jun 2007 02:49:10 +0900, Li Chen wrote:

  1. what is the best scenario to use Regexp.escape?

You use Regexp.escape when you’re building up a regular expression
programmatically as a String, and using Regexp.new to turn it into a
regular expression. In that case, all of the control codes in the string
will be interpreted, so if you have a string that needs to be matched
literally, then you use Regexp.escape to escape it first. This is also
the case when using variable interpolation.

airb(main):001:0> a="…"
=> “…”
irb(main):002:0> /#{a}/
=> /…/
irb(main):003:0> /#{Regexp.escape(a)}/
=> /…/

–Ken

  1. what is the best scenario to use Regexp.escape?

  2. I modify my codes and I get the expected results. But the odd is that
    I have to use 3 backslashes before the 2nd 2. How to explain this.

Thanks,

Li

DATA.each_line do |line|

      if line=~/1\.000000\\\$P1G\\1\.000000/
           line.gsub!(/1\.000000\\\$P1G\\1\.000000/, 

‘2.000000\$P1G\\2.000000’)
puts line
end
end

###same DATA as the first post##

####screen output####

ruby FC500_3.rb
xxx\2.000000$P1G\2.000000\xxx
yyyy\2.000000$P1G\2.000000\xxx
xxx\2.000000$P1G\2.000000\xxx
yyyy\2.000000$P1G\2.000000\xxx
xxx\2.000000$P1G\2.000000\xxx
yyyy\2.000000$P1G\2.000000\xxx