# Surprise in sub

**URL:** <https://www.ruby-forum.com/t/surprise-in-sub/134525>\
**Category:** Ruby\
**Created:** [April 11, 2008, 6:21pm UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525 "2008-04-11T18:21:14Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 11, 2008, 6:21pm UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/1 "2008-04-11T18:21:14Z")

</div>

irb(main):001:0\> s = “\\”  
=\> “\\”  
irb(main):002:0\> s.length  
=\> 2  
irb(main):003:0\> s = “howdy”.sub(“howdy”, s)  
=\> “\”  
irb(main):004:0\> s.length  
=\> 1

So merely using a string as the second param of sub (the replacement  
value) can cause that string to be altered.

Now, the documentation does “warn” that sequences \1, \2 etc. are valid  
in the replacement string. This suggests that the replacement string is  
processed before use; to be sure, it says nothing about “\” explicitly,  
but I do see of course that one must deal with “\” in order to escape  
the escaping. Furthermore, there’s a “workaround”, namely to write the  
third line as follows:

s = “howdy”.sub(“howdy”) {|x| s}

Still, I got seriously caught by this behavior and it was tricky to  
track down. m.

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 11, 2008, 8:15pm UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/2 "2008-04-11T20:15:53Z")

</div>

On Apr 11, 9:15 am, removed\_email\_address@domain.invalid (matt neuburg) wrote:

> value) can cause that string to be altered.  
> Still, I got seriously caught by this behavior and it was tricky to  
> track down. m.
> 
> –  
> matt neuburg, phd = removed\_email\_address@domain.invalid,[Matt Neuburg’s Home Page](http://www.tidbits.com/matt/)  
> Leopard -[http://www.takecontrolbooks.com/leopard-customizing.html](http://www.takecontrolbooks.com/leopard-customizing.html)  
> AppleScript -[Amazon.com](http://www.amazon.com/gp/product/0596102119)  
> Read TidBITS! It’s free and smart.[http://www.tidbits.com](http://www.tidbits.com)

s is changing because you assigned to it, not because of using it  
as the second parameter of sub(). Try assigning the result to a  
different variable like so:

ss = “howdy”.sub(“howdy”, s)

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 12, 2008, 12:51am UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/3 "2008-04-12T00:51:08Z")

</div>

x17y19 [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > So merely using a string as the second param of sub (the replacement
> 
> as the second parameter of sub(). Try assigning the result to a  
> different variable like so:
> 
> ss = “howdy”.sub(“howdy”, s)

You’re missing the point… m.

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 12, 2008, 6:14am UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/4 "2008-04-12T06:14:54Z")

</div>

From: matt neuburg [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

# You’re missing the point… m.

i think i missed the point too 🙂

you did mention: “So merely using a string as the second param of sub  
(the replacement value) can cause that string to be altered.”…

kind regards -botp

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 12, 2008, 3:45am UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/5 "2008-04-12T03:45:20Z")

</div>

Hi,

On Sat, Apr 12, 2008 at 2:20 AM, matt neuburg [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> irb(main):001:0\> s = “\\”  
> =\> “\\”  
> irb(main):002:0\> s.length  
> =\> 2  
> irb(main):003:0\> s = “howdy”.sub(“howdy”, s)  
> =\> “\”  
> irb(main):004:0\> s.length  
> =\> 1

Yeah, escaping and escaping-of-escaping with substition and Strings  
being  
used as a poor-man’s-regexp always catches me out. Thanks for the heads  
up  
on this one.

Arlen

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 12, 2008, 4:26pm UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/6 "2008-04-12T16:26:20Z")

</div>

On Fri, Apr 11, 2008 at 9:20 AM, matt neuburg [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> value) can cause that string to be altered.  
> Nope, using the string (s) as the second parameter of sub did nothing to  
> alter  
> it. This is clear if you use a different variable as the assignment  
> target:

irb(main):001:0\> s=‘\\’  
=\> “\\”  
irb(main):002:0\> s.length  
=\> 2  
irb(main):003:0\> foo = “howdy”.sub(“howdy”,s)  
=\> “\”  
irb(main):004:0\> s  
=\> “\\”  
irb(main):005:0\> s.length  
=\> 2  
irb(main):006:0\> foo  
=\> “\”  
irb(main):007:0\> foo.length  
=\> 1

s isn’t changed by being used as the second argument to sub, instead,  
the  
string sent as the second argument to sub is processed for escape  
sequences  
so that the substring ‘\’ occurring in that string is treated as a  
single literal ''  
when used in the replacement.

But its not changed, as the above irb session shows. s is unmodified.

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 12, 2008, 6:04pm UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/7 "2008-04-12T18:04:37Z")

</div>

On Sat, Apr 12, 2008 at 9:25 AM, Christopher D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> irb(main):002:0\> s.length  
> irb(main):007:0\> foo.length  
> =\> 1
> 
> s isn’t changed by being used as the second argument to sub, instead, the  
> string sent as the second argument to sub is processed for escape sequences  
> so that the substring ‘\’ occurring in that string is treated as a  
> single literal ''  
> when used in the replacement.
> 
> But its not changed, as the above irb session shows. s is unmodified.

When I first read the post, I immediately wanted to strike out with a  
“well, you’re assigning” response.

I’m not sure, but I think the OP was referring to what you said;  
namely, how the escaping happens before subbing.

Todd

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 13, 2008, 3:35pm UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/8 "2008-04-13T15:35:59Z")

</div>

Christopher D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > So merely using a string as the second param of sub (the replacement  
> > value) can cause that string to be altered.
> 
> Nope, using the string (s) as the second parameter of sub did nothing to alter  
> it.

I didn’t say that s was altered. I said that the string you provide as  
the second param of sub might not be the string that gets substituted in

- as the example demonstrates. If you don’t find this counterintuitive,  
you don’t; great. But some people might. Those are the people I’m trying  
to help here. m.

---

<div class="post-metadata">

**Author:** ![matt\_neuburg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4af34b/32.png) [@matt\_neuburg](https://www.ruby-forum.com/u/matt_neuburg)\
**Post date:** [April 15, 2008, 5:10am UTC](https://www.ruby-forum.com/t/surprise-in-sub/134525/9 "2008-04-15T05:10:48Z")

</div>

From: matt neuburg [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

# I didn’t say that s was altered. I said that the string you

# provide as the second param of sub might not be the string

# that gets substituted in - as the example demonstrates. If

# you don’t find this counterintuitive, you don’t; great. But

# some people might. Those are the people I’m trying

# to help here. m.

i think the confusion stems fr the fact that sub/gsub has to  
reprocess/unescape the string twice

1 for the string as usual for possible escaping chars like \ and "

and

2 for the group references like \1

note that this behaviour is present in other languages too.

it’s been a long time i have \*not used the string(as 2nd param) form. I  
have been getting used to w the block form since not only does it  
handles the double escaping issue/confusion but it also caters the match  
vars $1, $`, $& among others…

so, this one eg

irb(main):019:0\> “hello”.gsub(/([aeiou])/, “\<\1\>”)  
=\> “hll”

now becomes this

irb(main):020:0\> “hello”.gsub(/([aeiou])/) {|s| “\<#{s}\>”}  
=\> “hll”

or this

irb(main):026:0\> “hello”.gsub(/([aeiou])/) {“\<#$1\>”}  
=\> “hll”

your choice though.

kind regards -botp
