# Simple one-liners: last line missing

**URL:** <https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718>\
**Category:** Ruby\
**Created:** [March 13, 2006, 5:48pm UTC](https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718 "2006-03-13T17:48:34Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tobi\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ea666f/32.png) [@Tobi\_R](https://www.ruby-forum.com/u/Tobi_R)\
**Post date:** [March 13, 2006, 5:48pm UTC](https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718/1 "2006-03-13T17:48:34Z")

</div>

Hi

Let’s say I’d want to modify each line of a file. Here’s the dummy  
data:

$ cat data.txt  
first foo  
second foo  
third foo  
$

This works:

$ ruby -ne ‘$\_ =~ /(\S+)\s+(\S+)/;puts “#{$2} #{$1}”’ data.txt  
foo first  
foo second  
foo third  
$

I don’t really need to achieve that modification. Instead I’d like to  
understand why the following version one doesn’t work:

$ ruby -pe ‘sub(/(\S+)\s+(\S+)/,"#{$2} #{$1}")’ data.txt

foo first  
foo second  
$

TIA,  
Tobi

---

<div class="post-metadata">

**Author:** ![Tobi\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ea666f/32.png) [@Tobi\_R](https://www.ruby-forum.com/u/Tobi_R)\
**Post date:** [March 13, 2006, 6:13pm UTC](https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718/2 "2006-03-13T18:13:04Z")

</div>

> > > > > “T” == Tobi R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

T\> $ 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,

Guy Decoux

---

<div class="post-metadata">

**Author:** ![Tobi\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ea666f/32.png) [@Tobi\_R](https://www.ruby-forum.com/u/Tobi_R)\
**Post date:** [March 13, 2006, 6:19pm UTC](https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718/3 "2006-03-13T18:19:11Z")

</div>

On Tue, 14 Mar 2006 01:46:50 +0900, Tobi R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:  
[snip]

> I don’t really need to achieve that modification. Instead I’d like to  
> understand why the following version one doesn’t work:
> 
> $ ruby -pe ‘sub(/(\S+)\s+(\S+)/,“#{$2} #{$1}”)’ data.txt
> 
> foo first  
> foo second  
> $

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:

ruby -pe ‘sub(/(\S+)\s+(\S+)/,%q(\2 \1))’ data.txt

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

cheer’s  
andrew

---

<div class="post-metadata">

**Author:** ![Tobi\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ea666f/32.png) [@Tobi\_R](https://www.ruby-forum.com/u/Tobi_R)\
**Post date:** [March 13, 2006, 6:28pm UTC](https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718/4 "2006-03-13T18:28:24Z")

</div>

On Tue 2006-03-14 ts wrote:

> etc,

Thanks. I guess my (current) opinion is that it should work.

Tobi

---

<div class="post-metadata">

**Author:** ![Tobi\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ea666f/32.png) [@Tobi\_R](https://www.ruby-forum.com/u/Tobi_R)\
**Post date:** [March 13, 2006, 6:22pm UTC](https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718/5 "2006-03-13T18:22:13Z")

</div>

I think you want,

> ruby -pe ‘sub(/(\S+)\s+(\S+)/,"\2 \1")’ data.txt

---

<div class="post-metadata">

**Author:** ![Tobi\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ea666f/32.png) [@Tobi\_R](https://www.ruby-forum.com/u/Tobi_R)\
**Post date:** [March 13, 2006, 6:40pm UTC](https://www.ruby-forum.com/t/simple-one-liners-last-line-missing/54718/6 "2006-03-13T18:40:55Z")

</div>

On Tue 2006-03-14 Tobi R. wrote:

> > is ‘foo first’
> > 
> > etc,
> 
> Thanks. I guess my (current) opinion is that it should work.
> 
> Tobi

Now I understand that it can’t work.

Thanks again,  
Tobi
