gsub! and quoting question

R

Ronald Fischer

I thought this would be a trivial task, but it seems to be more
difficult than expected:

I have a variable, data, containing some string. I would like to
preprend every
single apostrophe in this string by a backslash. Here is my solution:

data.gsub!(/'/,%q(\\'))

Strangely, this does not work. I tested it with data containing a string
consisting
of a single quote solely, and surrounded the code by "puts" like this:

data=3D%q(')
puts ":"+data+" replace quotes by "+%q(\\')
data.gsub!(/'/,%q(\\'))
puts "data length now #{data.length}"

This produced as output:

:' replace quotes by \'
data length now 0

From this I conclude that the gsub! had shortened the string to length
zero.
Any explanation for this? How do I solve my problem in a proper way?

Ronald


--=20
Ronald Fischer <[email protected]>
Phone: +49-89-452133-162
 
R

Robert Klemme

2007/9/10 said:
I thought this would be a trivial task, but it seems to be more
difficult than expected:

I have a variable, data, containing some string. I would like to
preprend every
single apostrophe in this string by a backslash. Here is my solution:

data.gsub!(/'/,%q(\\'))

Strangely, this does not work. I tested it with data containing a string
consisting
of a single quote solely, and surrounded the code by "puts" like this:

data=%q(')
puts ":"+data+" replace quotes by "+%q(\\')
data.gsub!(/'/,%q(\\'))
puts "data length now #{data.length}"

This produced as output:

:' replace quotes by \'
data length now 0

From this I conclude that the gsub! had shortened the string to length
zero.
Any explanation for this? How do I solve my problem in a proper way?

This comes up frequently. You need to be aware that there are several
levels of interpretation involved and so you need multiple levels of
escaping. This is sometimes obscured by the fact that '\1' works
although it should read '\\1'. These levels are: 1. string escaping,
2. regexp replacement string escaping. All these variants do work:

str.gsub /'/, '\\\\\\&'
str.gsub /'/, '\\\\\''
str.gsub /'/, "\\\\'"

Kind regards

robert
 
R

Ronald Fischer

data=3D%q(')
=20
This comes up frequently.=20

I'm sorry if I posted a question which has been answered already :-(
You need to be aware that there are several
levels of interpretation involved and so you need multiple levels of
escaping. This is sometimes obscured by the fact that '\1' works
although it should read '\\1'. These levels are: 1. string escaping,
2. regexp replacement string escaping.=20

Hmmm... I would understand your argument if I had a digit following
a backslash (which would mean a backreference to the n-th group in
the pattern), but here we have \', and this is not a back reference,
isn't it? At least the discussion of String#gsub at
http://www.ruby-doc.org/core/
mentions only \1,\2,... etc. as back references.

Ronald
--=20
Ronald Fischer <[email protected]>
Phone: +49-89-452133-162
 
R

Robert Klemme

2007/9/10 said:
I'm sorry if I posted a question which has been answered already :-(


Hmmm... I would understand your argument if I had a digit following
a backslash (which would mean a backreference to the n-th group in
the pattern), but here we have \', and this is not a back reference,
isn't it? At least the discussion of String#gsub at
http://www.ruby-doc.org/core/
mentions only \1,\2,... etc. as back references.

No. You want the backslash to be interpreted literally by the regexp
engine, i.e. you want to prevent the regexp engine from identifying
the backslash as a meta character. This is independent from the
character *after* the backslash.

First, you need to escape every backslash in a string so it is
inserted literally (makes 2 backslashes). Then you need to escape a
backslash because otherwise the regexp engine will interpret it (makes
2*2=4 backslashes). Finally you need an additional backslash to ensure
the single quote is inserted into the string.

Btw, not only digits are meaningful in replacement patterns, but
single quote is as well (I believe it's the postmatch):

irb(main):012:0> puts "abc".gsub(/b/, '\\\'')
acc
=> nil
irb(main):013:0> puts "abc".gsub(/b/, '\\`')
aac
=> nil

Cheers

robert
 
R

Ronald Fischer

Hmmm... I would understand your argument if I had a digit following
=20
No. You want the backslash to be interpreted literally by the regexp
engine, i.e. you want to prevent the regexp engine from identifying
the backslash as a meta character. =20
OK

This is independent from the
character *after* the backslash.

Ah, that's the point I was missing. Now things are clear!
Btw, not only digits are meaningful in replacement patterns, but
single quote is as well (I believe it's the postmatch):

I already suspected this too (knowing this concept from Perl), but
didn't
find anything in the Ruby online docs where this would be discussed.
But this explains why my string was replaced by the empty string...

Ronald
--=20
Ronald Fischer <[email protected]>
Phone: +49-89-452133-162
 
W

William James

This comes up frequently. You need to be aware that there are several
levels of interpretation involved and so you need multiple levels of
escaping. This is sometimes obscured by the fact that '\1' works
although it should read '\\1'. These levels are: 1. string escaping,
2. regexp replacement string escaping. All these variants do work:

str.gsub /'/, '\\\\\\&'
str.gsub /'/, '\\\\\''
str.gsub /'/, "\\\\'"

str.gsub /(?=')/, "\\"
 

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,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top