rubygsubstring-interpolation

Ruby: replacement part include $1 $2 $3 and saved in a variable, but interpolation doesn't happen when using gsub


(a) the codes I wrote.

$str = '909090 aa bb cc dd ee ff 00 12345678 aa bb 12345678 aa bb cc dd ee ff 00 11 22 33 123456 FE 89'
puts $str
$str.gsub!(/\s+/, '')

search_1  = 'aa bb cc dd ee ff 00 (\S{8} aa bb \S{8} aa bb cc dd ee ff 00 11 22 33 \S{6}) (FF|FE) (89)'
puts search_1
search_1.gsub!(/\s+/, '')
replace_1 = '11 22 33 44 55 66 77 $1 $2 $3'
puts replace_1
replace_1.gsub!(/\s+/, '')

repls_1 = [
  [search_1, replace_1],
]


repls_1.each do |x|
  abc = $str.gsub(Regexp.new(x[0])) {
    x[1]
  }
  puts abc
end

(2) script running results

  909090 aa bb cc dd ee ff 00 12345678 aa bb 12345678 aa bb cc dd ee ff 00 11 22 33 123456 FE 89
  aa bb cc dd ee ff 00 (\S{8} aa bb \S{8} aa bb cc dd ee ff 00 11 22 33 \S{6}) (FF|FE) (89)
  11 22 33 44 55 66 77 $1 $2 $3

  90909011223344556677$1$2$3

The interpolation for $1, $2, $3 doesn't happen, is there way to solve it? Thanks.

(i) I don't want use \1 \2 \3, but $1 $2 $3)

(ii) There're more than one patterns, here only one example

(iii) matched parts numbers is not fixed, here is $1$2$3, other case is possible, such as ...$1...$2...$3...$5..., hope the codes can cover this variation on both captured parts number and position.


Solution

  • In Ruby, the gsub method does not support $1, $2, $3 etc. for interpolation in the replacement string. However you can use them in a block given to gsub as given below. Try modifying this code.

    repls_1.each do |x|
      abc = $str.gsub(Regexp.new(x[0])) {
        '11223344556677' + $1 + $2 + $3
      }
      puts abc
    end
    

    Edit

    $~ is a special variable that holds the MatchData object for the last match. The captures method returns an array of all the groups in the match and join concatenates them together. This will work no matter how many groups your regex has. So here is the code.

    repls_1.each do |x|
      abc = $str.gsub(Regexp.new(x[0])) {
        '11223344556677' + $~.captures.join
      }
      puts abc
    end