I'm trying to rewrite a command to replace output files with the same files in a different directory, building up a translation map. In Perl I could do something like this:
s{(-o|--out)\s((?:\S+\/)?(\S+))}{ "$1 " . ($m{$2}="foo/$3") }eg
I'm not clear how to do the same under Ruby, because:
"-out AAA -out yeah/BBB".
gsub(/((?:\s|^)-out)\s+((?:\S+\/)?(\S+))/) { |f|
"#{f[1]} #{m[f[2]] = "temp/#{f[3]}"}"
}
results in
"o temp/t- temp/u"
because 'm' is the matched string, not a match object, so #{m[1]}
is just the second character of the matched string.
I don't want to use $1
, $2
because Rubocop says they're evil, and I'd prefer not to use 'Regexp.last_match' because it's quite remarkably verbose and turns this one-liner into a do-block.
Is there no built-in that gives me the match object as the parameter?
Once you do not want to use $1
as you did in perl, you might use named matches:
"-out AAA -out BBB".gsub(/(?<leading>\s|^)(?<out>-out)\s+(?<rest>\S+)/) do
"#{$~[:leading]}#{$~[:out]} BLOCK"
end
#⇒ "-out BLOCK -out BLOCK"
Another option would be to shut rubocop up, since you know what you are doing:
#rubocop:disable Style/PerlBackrefs
"-out AAA -out BBB".gsub(/(\s|^)(-out)\s+(\S+)/) do
"#{$1}#{$2} BLOCK"
end
#rubocop:enable Style/PerlBackrefs