Forum: Ruby backreference is not working with #gsub

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**.
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.