Backreference is not working with #gsub

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

~>

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

Oh, and you may need the block mode of #gsub

Final thing: your regex won’t match your string, because the /rakshit/
part
is non-optional.

Matthew K. 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 `’

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 `’

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

>>

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 `’

Arup R. 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>’ )

>>

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 `’

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

Matthew K. wrote in post #1139656:

Arup R. 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.