Inconsistent regexp behavior

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)

I'm sorry, but you're wrong. :slight_smile: 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

···

On 14.08.2008 18:40, Glen Holcomb wrote:

[Note: parts of this message were removed to make it a legal post.]

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.

Glen Holcomb 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

···

--
NP: Disbelief - Coast To Coast (Bonus Track)
Jabber: sepp2k@jabber.org
ICQ: 205544826

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

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

···

On Thu, Aug 14, 2008 at 10:40 AM, Glen Holcomb <damnbigman@gmail.com> wrote:

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)

--
"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)

# 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

···

From: Glen Holcomb [mailto:damnbigman@gmail.com]

Thanks guys, now I know why.

···

On Thu, Aug 14, 2008 at 11:01 AM, Glen Holcomb <damnbigman@gmail.com> wrote:

On Thu, Aug 14, 2008 at 10:40 AM, Glen Holcomb <damnbigman@gmail.com> > wrote:

> 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)
>

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)

--
"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)

I was thinking about including a statement about the block form but
decided against - now you made me write it anyway... :slight_smile:

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

···

2008/8/15 Peña, Botp <botp@delmonte-phil.com>:

From: Glen Holcomb [mailto:damnbigman@gmail.com]
# 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

--
use.inject do |as, often| as.you_can - without end