String.sub strangeness

B

Belorion

Forgive me if my Monday fog is preventing me from seeing the simple
answer to this simple problem...

irb-enhanced(main):001:0> str = "123&456"
=> "123&456"
irb-enhanced(main):002:0> str.sub( /\&/, "\\&" )
=> "123&456"
irb-enhanced(main):003:0> str.sub( /\&/, "\\!" )
=> "123\\!456"


Why am I not able to escape the & in the string with an a \ ? If I do this:

irb-enhanced(main):004:0> str.sub( /\&/, "\\\\&" )
=> "123\\&456"

It seems to work... I'm not sure I understand the (apparent) inconsistency.
 
M

mark sparshatt

Belorion said:
Forgive me if my Monday fog is preventing me from seeing the simple
answer to this simple problem...

irb-enhanced(main):001:0> str = "123&456"
=> "123&456"
irb-enhanced(main):002:0> str.sub( /\&/, "\\&" )
=> "123&456"
irb-enhanced(main):003:0> str.sub( /\&/, "\\!" )
=> "123\\!456"
This is because when the string is created \\& is converted into \&. In
a substitution string \& refers to the part of the origional string
which matches the regexp.
Why am I not able to escape the & in the string with an a \ ? If I do this:

irb-enhanced(main):004:0> str.sub( /\&/, "\\\\&" )
=> "123\\&456"
Another way that works is to use the block form

str.sub!( /\&/) {"\\&"}

HTH
 
B

Belorion

This is because when the string is created \\& is converted into \&. In
a substitution string \& refers to the part of the origional string
which matches the regexp.

Ugh, silly me. Thanks Mark!
 
R

Robert Klemme

mark sparshatt said:
This is because when the string is created \\& is converted into \&. In a
substitution string \& refers to the part of the origional string which
matches the regexp.

That's exactly the right conversion! Apparently you've been fooled by IRB
which uses #inspect. Using puts to print the converted string sometimes
helps avoid confusion:
123\&456
=> nil

Note also:
\\&
=> nil

You need four backslashes because you want two backslashes in the
substitution string. The reason for that is that a backslash is a meta
character in a substitution string (for example if you use '\\2' for the
second group and '\\&' for the complete match) and thus you have to escape
it in order to get it literally.
Another way that works is to use the block form

str.sub!( /\&/) {"\\&"}

I've noticed that people quite often recommend to use the block form of
sub/gsub to cope with escaping. Please don't do that: the block form is
less performant than the direct form. It's applicable where the
substitution string (or rather pattern) has to change for each substitution.
All other cases should use the argument form.

Kind regards

robert
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top