# Regexp riddle; escaping escapes

**URL:** <https://www.ruby-forum.com/t/regexp-riddle-escaping-escapes/112330>\
**Category:** Ruby\
**Created:** [August 17, 2007, 4:32pm UTC](https://www.ruby-forum.com/t/regexp-riddle-escaping-escapes/112330 "2007-08-17T16:32:58Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [August 17, 2007, 4:32pm UTC](https://www.ruby-forum.com/t/regexp-riddle-escaping-escapes/112330/1 "2007-08-17T16:32:58Z")

</div>

Rubies:

Someone didn’t escape their & in their HTML correctly. Let’s fix it.

This regexp correctly does not escape &dude, because we only want to  
escape  
raw & markers:

p “yo &dude”.gsub(/&([^a-z])/i, ‘&\1’)

That passed “yo &dude” thru unchanged. (I am aware “dude” has no ; on  
the  
end; we are leaving that optional, for whatever reason…)

Now escape & followed by a non-alphabetic character:

p “yo & dude”.gsub(/&([^a-z])/i, ‘&\1’)

That correctly provides: “yo & dude”

Now how to escape “yo && dude”? Note that the ([^a-z]) consumes the  
second  
&, leading to this incorrect output:

“yo && dude”

The only workaround I can think of is to run the Regexp twice:

x = “yo && dude”  
2.times{ x.gsub!(/&([^a-z])/i, ‘&\1’) }  
p x

Can someone help my feeb Regexp skills and get a “yo && dude” in  
one  
line?

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [August 17, 2007, 4:55pm UTC](https://www.ruby-forum.com/t/regexp-riddle-escaping-escapes/112330/2 "2007-08-17T16:55:00Z")

</div>

On 8/17/07, Phlip [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> end; we are leaving that optional, for whatever reason…)  
> “yo && dude”
> 
> The only workaround I can think of is to run the Regexp twice:
> 
> x = “yo && dude”  
> 2.times{ x.gsub!(/&([^a-z])/i, ‘&\1’) }  
> p x
> 
> Can someone help my feeb Regexp skills and get a “yo && dude” in one  
> line?

str = “yo && dude”  
str.gsub!( %r/&(?=[^a-z])/i, ‘&’)  
p str  
=\> “yo && dude”

The regular expression trick here is the (?=re) That’s called the  
“zero-width positive lookahead”. It matches, but it does not consume  
the string; so the gsub! will only replace the characters that are NOT  
inside (?=re).

Blessings,  
TwP

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [August 17, 2007, 5:02pm UTC](https://www.ruby-forum.com/t/regexp-riddle-escaping-escapes/112330/3 "2007-08-17T17:02:03Z")

</div>

Tim P. wrote:

> str.gsub!( %r/&(?=[^a-z])/i, ‘&’)

Thanks!

> “zero-width positive lookahead”

Man, that was right there, but I was blocking on it. (-;

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [August 17, 2007, 5:41pm UTC](https://www.ruby-forum.com/t/regexp-riddle-escaping-escapes/112330/4 "2007-08-17T17:41:06Z")

</div>

On 8/17/07, Phlip [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Tim P. wrote:
> 
> > str.gsub!( %r/&(?=[^a-z])/i, ‘&’)
> 
> Thanks!
> 
> > “zero-width positive lookahead”
> 
> Man, that was right there, but I was blocking on it. (-;

I had to pull my pickaxe off the shelf and look it up, too. Page 327  
in the second edition if you’re interested in reading about it. It’s  
in the first edition, too, that is available online.

Blessings,  
TwP
