# Inconsistent regexp behavior

**URL:** <https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881>\
**Category:** Ruby\
**Created:** [August 14, 2008, 6:46pm UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881 "2008-08-14T18:46:44Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Glen\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/34f0e0/32.png) [@Glen\_H](https://www.ruby-forum.com/u/Glen_H)\
**Post date:** [August 14, 2008, 6:46pm UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881/1 "2008-08-14T18:46:44Z")

</div>

I have a script with two lines:

puts “toads suck”.gsub(/(\s)/, “\#{$1}”)

puts " a ".gsub(/(\s), “\#{$1}”)

I get broken output for the first:

toads\suck

\ a\

Can anyone explain why this is happening. I’m convinced it shouldn’t  
ever  
happen.

–  
“Hey brother Christian with your high and mighty errand, Your actions  
speak  
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)

---

<div class="post-metadata">

**Author:** ![Glen\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/34f0e0/32.png) [@Glen\_H](https://www.ruby-forum.com/u/Glen_H)\
**Post date:** [August 14, 2008, 7:03pm UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881/2 "2008-08-14T19:03:46Z")

</div>

On 14.08.2008 18:40, Glen H. wrote:

> toads\suck
> 
> \ a\
> 
> Can anyone explain why this is happening. I’m convinced it shouldn’t ever  
> happen.

I’m sorry, but you’re wrong. 🙂 When you pass “\#{$1}” to gsub the  
string is evaluated _once_ and even worse, the value of $1 at time of  
call has nothing to do with this gsub operation. gsub did not even  
start matching at this point in time.

The second replacement apparently works because it gets $1 from the  
first execution…

You also do not need the grouping because the group covers the whole  
match anyway. You rather want a special replacement expression:

irb(main):001:0\> “toads suck”.gsub(/\s/, ‘\\\&’)  
=\> “toads\ suck”  
irb(main):002:0\> puts “toads suck”.gsub(/\s/, ‘\\\&’)  
toads\ suck  
=\> nil

Note, the high number of backslashes is necessary because there are two  
levels of escaping: first the string, i.e. you need two backslashes to  
have one backslash in the string. Then you need to escape the backslash  
you want to insert into the replacement because backslash is a  
metacharacter in the substitution string itself.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![Glen\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/34f0e0/32.png) [@Glen\_H](https://www.ruby-forum.com/u/Glen_H)\
**Post date:** [August 14, 2008, 7:07pm UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881/3 "2008-08-14T19:07:52Z")

</div>

Glen H. wrote:

> puts “toads suck”.gsub(/(\s)/, “\#{$1}”)

Think about in what order the elements of this expression get evaluated.  
Then  
think about what the value of $1 is when “\#{$1}” gets evaluated.

HTH,  
Sebastian

---

<div class="post-metadata">

**Author:** ![Glen\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/34f0e0/32.png) [@Glen\_H](https://www.ruby-forum.com/u/Glen_H)\
**Post date:** [August 14, 2008, 7:09pm UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881/4 "2008-08-14T19:09:02Z")

</div>

On Thu, Aug 14, 2008 at 10:40 AM, Glen H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 

Oops. Typo, I should probably copy and paste next time. The second  
gsub is  
actually:

puts " a ".gsub(/(\s)/, “\#{$1}”)

–  
“Hey brother Christian with your high and mighty errand, Your actions  
speak  
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)

---

<div class="post-metadata">

**Author:** ![Glen\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/34f0e0/32.png) [@Glen\_H](https://www.ruby-forum.com/u/Glen_H)\
**Post date:** [August 14, 2008, 8:29pm UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881/5 "2008-08-14T20:29:29Z")

</div>

On Thu, Aug 14, 2008 at 11:01 AM, Glen H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > I get broken output for the first:  
> > "Hey brother Christian with your high and mighty errand, Your actions  
> > puts " a ".gsub(/(\s)/, “\#{$1}”)
> 
> –  
> “Hey brother Christian with your high and mighty errand, Your actions speak  
> so loud, I can’t hear a word you’re saying.”
> 
> -Greg Graffin (Bad Religion)

Thanks guys, now I know why.

–  
“Hey brother Christian with your high and mighty errand, Your actions  
speak  
so loud, I can’t hear a word you’re saying.”

-Greg Graffin (Bad Religion)

---

<div class="post-metadata">

**Author:** ![Glen\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/34f0e0/32.png) [@Glen\_H](https://www.ruby-forum.com/u/Glen_H)\
**Post date:** [August 15, 2008, 2:49am UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881/6 "2008-08-15T02:49:02Z")

</div>

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

# puts “toads suck”.gsub(/(\s)/, “\#{$1}”)

# toads\suck

# Can anyone explain why this is happening. I’m convinced it

# shouldn’t ever happen.

it’s a common surprise, but ruby has a solution for that; try the block  
form

irb(main):002:0\> puts “toads suck”.gsub(/(\s)/) { “\#{$1}” }  
toads\ suck  
=\> nil

no surprise.

kind regards -botp

---

<div class="post-metadata">

**Author:** ![Glen\_H](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/34f0e0/32.png) [@Glen\_H](https://www.ruby-forum.com/u/Glen_H)\
**Post date:** [August 15, 2008, 11:21am UTC](https://www.ruby-forum.com/t/inconsistent-regexp-behavior/145881/7 "2008-08-15T11:21:47Z")

</div>

2008/8/15 Peña, Botp [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> =\> nil  
> I was thinking about including a statement about the block form but  
> decided against - now you made me write it anyway… 🙂

IMHO the block form should be restricted to cases where substitutions  
should be done that cannot be implemented with simple pattern  
replacement (e.g. inserting a match counter, doing lookups somewhere  
etc.). This is mainly because I find the non block form more  
appropriate if you are only doing pattern replacements but it also has  
the nice side effect of being more efficient. Use the right tool for  
the job.

Kind regards

robert
