Forum: Ruby backreference is not working with #gsub

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-03-12 21:14
map = { "arup" => "1989"}
puts "arup rakshit".gsub(/(arup)rakshit/, map[\1] ) # !> possibly
useless use of a literal in void context
# ~> -:2: syntax error, unexpected $undefined, expecting ']'
# ~> puts "arup rakshit".gsub(/(arup)rakshit/, map[\1] )
# ~>
3df767279ce7d81db0a5bb30f5136863?d=identicon&s=25 Matthew Kerwin (mattyk)
on 2014-03-12 22:50
(Received via mailing list)
\1 isn't a variable name, it's a string escape sequence. It will only
work
inside a string. Try either map['\1'] or map[$1]

(I just woke up so my head may still be cloudy.)
3df767279ce7d81db0a5bb30f5136863?d=identicon&s=25 Matthew Kerwin (mattyk)
on 2014-03-12 22:51
(Received via mailing list)
Oh, and you may need the block mode of #gsub
3df767279ce7d81db0a5bb30f5136863?d=identicon&s=25 Matthew Kerwin (mattyk)
on 2014-03-12 22:53
(Received via mailing list)
Final thing: your regex won't match your string, because the /rakshit/
part
is non-optional.
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-03-12 23:04
Matthew Kerwin wrote in post #1139645:
> \1 isn't a variable name, it's a string escape sequence. It will only
> work
> inside a string. Try either map['\1']

map = { "arup" => "1989"}
puts "arup rakshit".gsub(/(arup)\s+rakshit/, map['\1'] )
# ~> -:2:in `gsub': no implicit conversion of nil into String
(TypeError)
# ~>   from -:2:in `<main>'

or map[$1]

map = { "arup" => "1989"}
puts "arup rakshit".gsub(/(arup)\s+rakshit/, map[$1] )
# ~> -:2:in `gsub': no implicit conversion of nil into String
(TypeError)
# ~>   from -:2:in `<main>'

$1,$2 etc work with blocks.

>
> (I just woke up so my head may still be cloudy.)


My question is when the below is working :

map = { "arup" => "1989"} # !> assigned but unused variable - map
puts "arup rakshit".gsub(/(arup)\s+rakshit/, '<\1>' )
# >> <arup>

Why not below ?

map = { "arup" => "1989"}
puts "arup rakshit".gsub(/(arup)\s+rakshit/, map['\1'] )
# ~> -:2:in `gsub': no implicit conversion of nil into String
(TypeError)
# ~>   from -:2:in `<main>'
3df767279ce7d81db0a5bb30f5136863?d=identicon&s=25 Matthew Kerwin (mattyk)
on 2014-03-13 00:42
Arup Rakshit wrote in post #1139651:
> My question is when the below is working :
>
> map = { "arup" => "1989"} # !> assigned but unused variable - map
> puts "arup rakshit".gsub(/(arup)\s+rakshit/, '<\1>' )
> # >> <arup>
>
> Why not below ?
>
> map = { "arup" => "1989"}
> puts "arup rakshit".gsub(/(arup)\s+rakshit/, map['\1'] )
> # ~> -:2:in `gsub': no implicit conversion of nil into String
> (TypeError)
> # ~>   from -:2:in `<main>'

Ah, this is a timing issue. You have to consider the point (in time) at
which each expression is evaluated.

For example:

  'abc'.gsub(/b/, '<\1>')

  1. 'abc' is evaluated, to give the String object
  2. .gsub is looked up in the method table
  3. /b/ is evaluated, to give a Regexp object
  4. '<\1>' is evaluated, to give a String object
  5. String#gsub is invoked, with 'abc', /b/, '<\1>' as
     receivers/parameters, resulting in your output

versus:

  'abc'.gsub(/b/, map['\1'])

  1. 'abc' is evaluated, to give the String object
  2. .gsub is looked up in the String's method table
  3. /b/ is evaluated, to give a Regexp object
  4. map is looked up in the lvar table, giving a Hash object
  5. [] is looked up in the Hash's method table
  6. '\1' is evaluated, giving a String object
  7. Hash#[] is invoked, with map, '\1' as receivers/parameters,
     resulting in `nil`
  8. String#gsub is invoked, with 'abc', /b/, nil as
     receivers/parameters, resulting in failure

Also note that the "\1" backref _only_ works when it's present in the
string given as the second parameter to #gsub
249c7fd851c5c5ac5a1abdb756472ae1?d=identicon&s=25 Arup Rakshit (my-ruby)
on 2014-03-13 08:44
Matthew Kerwin wrote in post #1139656:
> Arup Rakshit wrote in post #1139651:

> Also note that the "\1" backref _only_ works when it's present in the
> string given as the second parameter to #gsub

Nice explanation. Yes, that specific stuffs very hard to recognize in
Ruby. When I am sending `'<\1>'`, all is ok. But when trying to do it
`map['\1']`
or `"#{map[\\1]}"` **objections**.

so back-reference is not a global operation with `gsub`, it has a
**limitations**.
This topic is locked and can not be replied to.