8

I have some file like this :

abc 123    
abc 789  
bcd 456  
acb 135

I would like to print first column of next line in current line.

Desired output:

abc  123 abc  
abc 789 bcd  
bcd 456 acb  
acb 135 

I prefer to use awk.

4 Answers 4

17

Memorise the previous line:

awk 'NR > 1 { print prev, $1 } { prev = $0 } END { print prev }'

This processes the input as follows:

  • if the current line is the second or greater, print the previous line (stored in prev, see the next step) and the first field of the current line, separated by the output field separator (the space character by default);
  • in all cases, store the current line in the prev variable;
  • at the end of the file, print the previous line.
11

Alternative awk approach:

$ awk 'NR == 1{printf "%s", $0;next}{printf " %s\n%s", $1,$0}' input.txt                                    
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

The way this works is simple: first line is special case - we print it without new-line, and tell awk to go to next line without executing other code blocks. After that, NR == 1{printf "%s", $0;next} is skipped, but other parts do the job.

Remember that up to now we printed a formatted string without new line character. Thus , what is being done by printf " %s\n%s",$1,$0 now is first word is printed out ( and because there was no newline, it remains on the same line of output) , newline inserted, and then whole line itself ( but doesn't terminate with newline character). Thus next first word inserted will remain on the same line. Process continues on and on till we reach the end of file.

Possible improvement is to include END{print ""} block to insert final newline. In certain cases where resulting file is to be processed by other scripts it might be desirable.


While the user requested AWK specifically, same approach with printing formatted strings can be taken with other languages, for instance Python. Python alternative provided for those curious about how this can be implemented in other languages:

#!/usr/bin/env python
from __future__ import print_function
import sys

old = None
for index,line in enumerate(sys.stdin):
    if index == 0:
        print(line.strip(),end=" ")
        continue
    words = line.strip().split()
    print(words[0] + "\n" + line.strip(),end=" ")

And usage like so:

$ ./append_first.py < input.txt                            
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

Same idea about final newline applies here.

0
9

Here is an ugly sed way just for fun

sed '2,$ s/[^ ]\+/& &/; 2,$ s/ /\n/' file | paste -d ' ' - -
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135 

Explanation

  • 2,$ from the second line to the last
  • s/[^ ]\+/& &/ double the first set of non whitespace characters
  • ; separates commands, like in the shell
  • s/ /\n/ replace the first space with a newline
  • paste -d ' ' - - stick this mess together (append second line to third, fourth line to third, etc)
3
  • 1
    Alternatively you could use sed on its own without paste: sed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt Jan 13, 2017 at 0:19
  • 1
    If you write sed programs for fun, then perhaps you should have a go at code-golf ;-) Jan 13, 2017 at 0:34
  • 1
    @DigitalTrauma she's been on code-golf for 2 month already ;) Jan 13, 2017 at 3:43
1

In my opinion the simplest and most readable approach is:

  1. extract the first column (cut)
  2. delete the first line from your extracted column (tail)
  3. paste this column into your source file (paste)

Example: your sample inpult file:

abc 123    
abc 789  
bcd 456  
acb 135

Then run the following command in a terminal

cut -d' ' -f1 in.txt | tail -n +2 | paste -d' ' file -

Output:

abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

The structure behind this solution differs from the given answers. No need of conditions, loops or regular expression.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .