gsub!, replace with \'

P

Patrick Gundlach

Dear Ruby-hackers,

simple problem: replace a certain letter with \' (backslash apostrophe).

------------------------------
#!/usr/bin/ruby -w
puts "hello".gsub!(/h/,"\\'")
------------------------------

result: elloello

I would like to get:

\'ello

What should I try?


Patrick
 
A

Andreas Schwarz

Patrick said:
Dear Ruby-hackers,

simple problem: replace a certain letter with \' (backslash apostrophe).

------------------------------
#!/usr/bin/ruby -w
puts "hello".gsub!(/h/,"\\'")
------------------------------

result: elloello

I would like to get:

\'ello

What should I try?

puts "hello".gsub!(/h/,"\\\\'")

"\\" is reserved for backreferences.
 
S

Simon Strandgaard

Andreas said:
puts "hello".gsub!(/h/,"\\\\'")

"\\" is reserved for backreferences.

In the above case \' (slash quote) are interpreted as post-match.

Other useful things in replacement string:
\` pre-match
\+ last-capture
\& match
 
P

Patrick Gundlach

Andreas Schwarz said:
puts "hello".gsub!(/h/,"\\\\'")

"\\" is reserved for backreferences.

Hello Andreas,

Oh, yes. This works fine. Thank you (and of course Simon).

Patrick
 
S

Simon Strandgaard

Patrick Gundlach said:
Hello Andreas,

Oh, yes. This works fine. Thank you (and of course Simon).

Another way to obtain same result.. without extra escaping.

puts "hello".gsub!(/h/) {|m| "\\'"}
 
R

Robert Klemme

Simon Strandgaard said:
Another way to obtain same result.. without extra escaping.

puts "hello".gsub!(/h/) {|m| "\\'"}
Or
\'ello

Note:
\\'


You need an escaped backslash to prevent interpretation of it in the
replacement pattern.

robert
 
S

Simon Strandgaard

Robert Klemme said:
\\'


You need an escaped backslash to prevent interpretation of it in the
replacement pattern.

I remember when I switched to Ruby, I had difficulties understanding
the escaping rules in conjunction with single/double quotes.
String#gsub got me really confused.

I think I read somewhere that perl6 uses $ in the regexp replacement string,
in order to avoid our escaping hell. I think this is a good initiative.
So escape can be used freely:
"hello".gsub!(/h/, %q|\'|) #-> \'ello
"hello".gsub!(/(.)$1/, '$&$1') #-> helllo

Maybe we should do an RCR.. use dollar in regexp?
 
R

Robert Klemme

Simon Strandgaard said:
I remember when I switched to Ruby, I had difficulties understanding
the escaping rules in conjunction with single/double quotes.
String#gsub got me really confused.

It took some time for me, too.
I think I read somewhere that perl6 uses $ in the regexp replacement string,
in order to avoid our escaping hell. I think this is a good initiative.
So escape can be used freely:
"hello".gsub!(/h/, %q|\'|) #-> \'ello
"hello".gsub!(/(.)$1/, '$&$1') #-> helllo

Maybe we should do an RCR.. use dollar in regexp?

IMHO that would break too much code.

After all quoting rules are very logical: Step 1: "" and '' quoting rules
apply. Step 2: Then the gsub quoting rules apply to the result of step 1.

IMHO confusion often results from testing in irb which will print an
escaping backslash before each backslash in a string thus irritating people
about the contents of the string printed:
\
=> nil

Another source of confusion is the lax treatment of backslashes:
\1
=> nil\1
=> nil

Normally you would have to use the second form only, that would be more
logical IMHO.

Regards

robert
 
D

David Alan Black

Hi --

Simon Strandgaard said:
I think I read somewhere that perl6 uses $ in the regexp replacement string,
in order to avoid our escaping hell. I think this is a good initiative.
So escape can be used freely:
"hello".gsub!(/h/, %q|\'|) #-> \'ello
"hello".gsub!(/(.)$1/, '$&$1') #-> helllo

Maybe we should do an RCR.. use dollar in regexp?

Hmmm... I thought Ruby was moving more in the direction of getting rid
of Perl-like global variables :) But anyway, I think the thing you're
describing might lead to some awkward things. I think it's more logical
to treat $1 as just a regular variable for purposes of compiling the
regular expression:

/(def)/.match("abcdef")
puts $1 # def
/ABC#{$1.upcase}/.match("whatever")

If your change were made, $1 would be nil in the last line because
there are no captures.

And here, you'd get a kind of postponed compilation of re:

/(abc)/.match("abc")
re = /(blah)#{$1}def/

Sorry for the dumb examples... but I think the problems would be real.


David
 
S

Simon Strandgaard

David said:
Hmmm... I thought Ruby was moving more in the direction of getting rid
of Perl-like global variables :) But anyway, I think the thing you're
describing might lead to some awkward things. I think it's more logical
to treat $1 as just a regular variable for purposes of compiling the
regular expression:

/(def)/.match("abcdef")
puts $1 # def
/ABC#{$1.upcase}/.match("whatever")

If your change were made, $1 would be nil in the last line because
there are no captures.

And here, you'd get a kind of postponed compilation of re:

/(abc)/.match("abc")
re = /(blah)#{$1}def/

Sorry for the dumb examples... but I think the problems would be real.

At first sight I wondered what you are talking about.
I have never done any perl programming in my life.
IIUC perl interpolates $ inside strings.. that gave me a clue to
what you are talking about.

Ruby should of cause not interpolate global variables! :)
 
D

David Alan Black

Hi --

Simon Strandgaard said:
At first sight I wondered what you are talking about.
I have never done any perl programming in my life.
IIUC perl interpolates $ inside strings.. that gave me a clue to
what you are talking about.

I'm not sure why :) It was pure Ruby, not related to Perl.
Ruby should of cause not interpolate global variables! :)

Now I'm confused.... Why not? Or do you mean interpolate without
#{...} ?


David
 
M

Mark Hubbart

Hi --



Hmmm... I thought Ruby was moving more in the direction of getting rid
of Perl-like global variables :) But anyway, I think the thing you're
describing might lead to some awkward things. I think it's more
logical
to treat $1 as just a regular variable for purposes of compiling the
regular expression:

/(def)/.match("abcdef")
puts $1 # def
/ABC#{$1.upcase}/.match("whatever")

If your change were made, $1 would be nil in the last line because
there are no captures.

And here, you'd get a kind of postponed compilation of re:

/(abc)/.match("abc")
re = /(blah)#{$1}def/

Sorry for the dumb examples... but I think the problems would be real.

hmm? I think the suggestion has nothing to do with the #{...} construct
for interpolation. I think Simon is suggesting allowing "$1$2" as an
alternative to "\\1\\2". These are things that would never be
interpolated in current scheme. I think this would make things clearer,
much less confusing. The backslash escaping rules are complicated
enough that I never use them; I only use the block form of sub and
gsub.

note that

/(\d+)$1/.match(str)

would be entirely different from

/(\d+)#{$1}/.match(str)

as the first would match something like this: "12341234" and the second
would match "1276#{$1}", with whatever $1 is interpolated as.

cheers,
Mark
 
S

Simon Strandgaard

David said:
I'm not sure why :) It was pure Ruby, not related to Perl.


Now I'm confused.... Why not? Or do you mean interpolate without
#{...} ?

Agree we have lost syncronization here :)

Mark Hubbart has made an reply where he talk about the $ idea,
that mail describes exactly what I had in mind to say.
http://ruby-talk.org/101910
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top