When doing substitutions with a string replacement, you do not get what
you might expect because the interpolation of #{$1} in the replacement
string happens when the arguments are evaluated and passed into the sub()
or gsub() methods, not during the match. That means they will have whatever
value they had from the last successful match (or nil, as in your case with
the first line printed).
To access backreferences within a replacement string, you may use the same
notation as you do for backreferences within the pattern itself: \1, \2,
etc. For your example:
Alternatively, you may use the block form of replacement, in which case the
block is evaluated at match-time and $1, $2, etc are available and refer to
their respective backreferences within the current match:
>
> > $ ruby -pe 'sub(/(\S+)\s+(\S+)/,"#{$2} #{$1}")' data.txt
>
> The replacement string is build when #sub is called
>
> for the first call $1 = $2 = nil ==> the replacement string is ' '
>
> for the second call, $1 = 'first', $2 = 'foo' ==> the replacement string
> is 'foo first'
>
> etc,
Thanks. I guess my (current) opinion is that it should work.