Rob Biedenharn wrote: > On Jan 25, 2010, at 12:00 PM, lalawawa wrote: > >> Actually, I oversimplified my example. I want to escape single >> quotes and question marks. >> >> irb(main):001:0> a = "Can't we?" >> => "Can't we?" >> irb(main):002:0> a.gsub(/([\'\?])/, '\\1') >> => "Can't we?" >> irb(main):003:0> a.gsub(/([\'\?])/, '\\\1') >> => "Can\\1t we\\1" >> irb(main):004:0> a.gsub(/([\'\?])/, '\\\\1') >> => "Can\\1t we\\1" >> irb(main):005:0> a.gsub(/([\'\?])/, '\\\\\1') >> => "Can\\'t we\\?" > > > (Well, Mike's answer steals my thunder a bit, but I'll put this out > there for anyone else that finds this thread.) > > > You just have to remember that there's two levels of confusion, uh, I > mean *escaping* going on here. > > Within single-quoted strings, the only backslash-escape is for a ' > and, so you can have a \, you also need to escape the escape character: > > '\1' means a backslash and a digit (because the character following > the \ is not ' or \ it doesn't have its special meaning) > '\\1' means an escaped backslash and a digit (yes, the same as above, > but this time the first \ escapes the second \ so that it is > interpreted literally) > '\\\1' means an escaped backslash, a backslash, and a digit (you see > where this is going, right?) > > Now, within the replacement string for a gsub, you can have a > backslash-digit to mean "the n-th parenthesized group where the digit > is n" > > So you want to replace with "a backslash and a backslash-digit for the > first group". You need the final interpretation of the replacement to > end up as \ \1 (no quotes here to confuse things) > > '\\' is a literal \ > '\\\\' is a literal \\ so gsub will see a real \ > '\1' is \1 because 1 isn't a special character > SO... > '\\\\\1' is seen as \\\1 (as the argument) and gsub interprets it as > "literal backslash, first group" > > '\\\\\\1' is seen the same way; the fifth backslash escapes the sixth, > then the 1 > > You might consider using the block form of gsub replacement. > > irb> a = "Can't we?" > => "Can't we?" > irb> a.gsub(/(['?])/, '\\\\\\1') > => "Can\\'t we\\?" > irb> puts _ > Can\'t we\? > => nil > irb> a.gsub(/['?]/) {|m| '\\' + m} > => "Can\\'t we\\?" > irb> puts _ > Can\'t we\? > => nil > > In your case, the clarity that results from the simplification of the > replacement should be obvious. > > -Rob > > Rob Biedenharn http://agileconsultingllc.com > Rob / AgileConsultingLLC.com > Most excellent and informative posts, Rob and Mike. I've saved them both to my "best of Ruby" folder.