# Weird behaviour escaping special characters in a string

**URL:** <https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363>\
**Category:** Ruby\
**Created:** [February 21, 2007, 6:55pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363 "2007-02-21T18:55:24Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 21, 2007, 6:55pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/1 "2007-02-21T18:55:24Z")

</div>

This instance method added to the String class returns a copy of the  
receiver with occurrences of \ replaced with \, and occurrences of ’  
replaced with ':

class String  
def to\_source\_string  
gsub(/(\|’)/, ‘\\\1’)  
end  
end

The idea is that it will give you a string that you can write out a  
Ruby file that will later print the string. For, example, let’s take  
the string, foo (3 characters):

“puts '” + “foo”.to\_source\_string + “’” # puts ‘foo’

Or a string with special characters in it like ‘foo’ (5 characters,  
including enclosing single quotes):

“puts '” + “‘foo’”.to\_source\_string + “’” # puts ‘‘foo’’

My RSpec specs and experimentation in irb confirm that the method  
works but I am at a loss to explain one thing:

Why do I need so many backslashes in my replacement expression?

There are five slashes in the replacement expression:

```
gsub(/(\\|')/, '\\\\\1')

```

But I would have thought that three would work:

```
gsub(/(\\|')/, '\\\1')

```

I basically want to replace “whatever is found in the pattern” with a  
backslash (\) followed by “whatever was found” (\1); so that’s three  
slashes. But with only three slashes Ruby gives me \1foo\1 instead of  
‘foo’. Four slashes produces the same result. Five slashes and  
suddenly everything works (funnily enough, six slashes also works).  
Two slashes and one slash have no effect (no escaping is performed).

I’ve got working code so it’s not a huge problem, but my curiosity is  
piqued. What’s going on here that I don’t understand?

Cheers,  
Greg

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 21, 2007, 7:37pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/2 "2007-02-21T19:37:35Z")

</div>

On 2/21/07, Greg H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> This instance method added to the String class returns a copy of the  
> receiver with occurrences of \ replaced with \, and occurrences of ’  
> replaced with ':
> 
> class String  
> def to\_source\_string  
> gsub(/(\|')/, ‘\\\1’)  
> end  
> end

class String  
def to\_source\_string  
gsub(/(\|')/) { “\#$1” }  
end  
end

-austin

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 21, 2007, 7:45pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/3 "2007-02-21T19:45:37Z")

</div>

On Feb 21, 2007, at 12:36 PM, Austin Z. wrote:

> class String  
> def to\_source\_string  
> gsub(/(\|’)/) { “\#$1” }  
> end  
> end

It’s probably better to use a character class [\’] instead of  
alternation (\|’).

James Edward G. II

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 21, 2007, 8:50pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/4 "2007-02-21T20:50:54Z")

</div>

On Thu, Feb 22, 2007 at 02:55:09AM +0900, Greg H. wrote:

> Why do I need so many backslashes in my replacement expression?
> 
> There are five slashes in the replacement expression:
> 
> ```
> gsub(/(\\|')/, '\\\\\1')
> 
> ```
> 
> But I would have thought that three would work:
> 
> ```
> gsub(/(\\|')/, '\\\1')
> 
> ```

Because even in single quotes, blackslashes must be doubled; this in  
turn is  
because ’ is the way that you insert a single quote within a  
single-quoted  
string.

irb(main):001:0\> a=’\’  
=\> “\”  
irb(main):002:0\> a.size  
=\> 1  
irb(main):003:0\> b=’’’  
=\> “’”  
irb(main):004:0\> b.size  
=\> 1  
irb(main):005:0\> c=’\x’  
=\> “\x”  
irb(main):006:0\> c.size  
=\> 2

> I basically want to replace “whatever is found in the pattern” with a  
> backslash (\) followed by “whatever was found” (\1); so that’s three  
> slashes. But with only three slashes Ruby gives me \1foo\1 instead of  
> ‘foo’. Four slashes produces the same result. Five slashes and  
> suddenly everything works (funnily enough, six slashes also works).  
> Two slashes and one slash have no effect (no escaping is performed).
> 
> I’ve got working code so it’s not a huge problem, but my curiosity is  
> piqued. What’s going on here that I don’t understand?

irb(main):009:0\> a=’\\1’  
=\> “\\1”  
irb(main):010:0\> a.size  
=\> 3  
irb(main):011:0\> a=’\\\1’  
=\> “\\\1”  
irb(main):012:0\> a.size  
=\> 4  
irb(main):013:0\> a=’\\\1’  
=\> “\\\1”  
irb(main):014:0\> a.size  
=\> 4

In a single-quoted string:  
’ =\> ’  
\ =\>   
\x =\> \x for all other x

So ‘…\1’ and ‘…\1’ are identical.

HTH,

Brian.

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 22, 2007, 2:00pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/5 "2007-02-22T14:00:28Z")

</div>

On 21 feb, 19:45, James Edward G. II [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> On Feb 21, 2007, at 12:36 PM, Austin Z. wrote:
> 
> It’s probably better to use a character class [\‘] instead of  
> alternation (\|’).
> 
> James Edward G. II

I did some quick and dirty benchmarks and using a character class is a  
little bit quicker. Interpolation (“\#$1”) is slower but more  
readable. I guess I’ll stick with the character class and no  
interpolation though.

require ‘benchmark’  
include Benchmark

bm(6) do |x|  
x.report(‘alternation’) { 100\_000.times { “‘foo’”.gsub(/(\|‘)/, ‘\  
\1’) } }  
x.report(‘char class’) { 100\_000.times { “‘foo’”.gsub(/[\’]/, ‘\\  
&’) } }  
x.report(‘interpolation’) { 100\_000.times { “‘foo’”.gsub(/(\|‘)/, "  
#$1") } }  
x.report(‘interpolation with char class’) { 100\_000.times  
{ “‘foo’”.gsub(/[\’]/, “\#$&”) } }  
end  
user system total real  
alternation 0.450000 0.000000 0.450000 ( 0.452661)  
char class 0.390000 0.000000 0.390000 ( 0.396193)  
interpolation 0.540000 0.010000 0.550000 ( 0.532106)  
interpolation with char class 0.480000 0.000000 0.480000  
( 0.485922)

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 22, 2007, 2:06pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/6 "2007-02-22T14:06:29Z")

</div>

On Thu, 22 Feb 2007 13:55:06 +0100, Greg H.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 4 slashes, and the same for 5 and 6 slashes.

%q{…} is your friend.

David V.

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 22, 2007, 1:55pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/7 "2007-02-22T13:55:28Z")

</div>

On 21 feb, 20:50, Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> In a single-quoted string:  
> ' =\> ’  
> \ =\>   
> \x =\> \x for all other x
> 
> So ‘…\1’ and ‘…\1’ are identical.

Excellent, that explains why I was getting the same results for 3 and  
4 slashes, and the same for 5 and 6 slashes.

Cheers,  
Greg

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [February 22, 2007, 2:18pm UTC](https://www.ruby-forum.com/t/weird-behaviour-escaping-special-characters-in-a-string/86363/8 "2007-02-22T14:18:30Z")

</div>

2007/2/21, Greg H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> The idea is that it will give you a string that you can write out a  
> Ruby file that will later print the string. For, example, let’s take  
> the string, foo (3 characters):
> 
> “puts '” + “foo”.to\_source\_string + “'” # puts ‘foo’
> 
> Or a string with special characters in it like ‘foo’ (5 characters,  
> including enclosing single quotes):
> 
> “puts '” + “‘foo’”.to\_source\_string + “'” # puts ‘'foo'’

Why don’t you just use #inspect?

Kind regards

robert
