Can someone please tell me what does this do?

cat infile|
awk ' 
 for(i=3;i<=NF;i++){ $2=$2" "$i } 
 printf "%-4s %s\n", $1,$2 ; 
}' > outfile.txt    

infile contains:

1 John Smith  
2 Bill Johnson  
5000 George Heiz  

I see that the result is that outfile.txt has all the lines aligned but I don't understand how
Specifically what does this part for(i=3;i<=NF;i++){ $2=$2" "$i } do?

  • Are you sure it's infile| rather than cat infile|? – Joseph R. Sep 14 '13 at 20:53
  • @JosephR:You are right.I just wanted to highlight the part that I don't understand – Jim Sep 14 '13 at 20:55
  • Thanks for this question, breaking up our day here, and I never thought to concatenate in this manner, might be useful down the road! – slm Sep 14 '13 at 21:13

With these awk scripts I always find it best to break them down so I can see what's going on.


This one is easy. That's formatting the output of the original columns $1 and $2 so that the column $1 is padded so that it takes up 4 spaces.


$ cat infile | awk ' 
 for(i=3;i<=NF;i++){ $2=$2" "$i } 
 printf "%-4s DDD\n", $1 ; 
1    DDD
2    DDD
5000 DDD

for loop

This one is a little trickier to detect, but it's taking any columns that are 3 or greater and concatenating them to column $2.

$ cat infile | awk ' 
 for(i=3;i<=NF;i++){ $2=$2" "$i } 
 printf "%s | %s\n", $2,$3 ; 
John Smith | Smith
Bill Johnson | Johnson
George Heiz | Heiz

This makes it slightly easier, but really if we add a 4th column to infile then it's more obvious:

$ cat infile 
1 John Smith 4thcol
2 Bill Johnson 4thcol

5000 George Heiz 4thcol


$ cat infile | awk ' 
 for(i=3;i<=NF;i++){ $2=$2" "$i } 
 printf "%s\t|\t%s\n", $2,$3 ; 
John Smith 4thcol   |   Smith
Bill Johnson 4thcol |   Johnson
George Heiz 4thcol  |   Heiz

If we add a 5thcol, and so on they'll keep getting appended to $2.


This awk script is a convoluted and inefficient way to do what can be rewritten that way:

awk '
 printf "%4d %s\n",f,$0 ;
}' infile > outfile.txt

This latter script records in the f variable the first field, then clears it, then print the f variable aligned on four characters followed by the remaining of the original line unchanged.

I guess the author didn't figure it out how to format the first field while keeping the rest of the record alone and so put all of the remaining fields in the second one with the odd loop.


There is even a simpler way suggested by rici:

awk '{$1 = sprintf("%4d", $1); print}' infile > outfile.txt

This one simply replace the first field by its formatted representation and output the line.

  • 1
    Even simpler: {$1 = sprintf("%4d", $1); print} (or "%-4s" as in the original) – rici Sep 14 '13 at 23:58
  • no worries. It's actually possible to just use $1 = sprintf("%4d", $1) without braces or print statement, but explaining why it works is way more effort than its worth. (Yes, it does work if $1 is 0. awk is full of little details.) – rici Sep 15 '13 at 1:05
  • @rici ;-) . . . . . . – jlliagre Sep 15 '13 at 1:08

You have the formatting commands in printf as the first argument string. %-4s indicates the output to be allocated 4 characters and left aligned. Then, there is a space, followed by the string, indicated by %s.

  • I figured this.But what is the for loop doing? – Jim Sep 14 '13 at 21:02
  • The loop is working on all records that have 3 or more fields. However, the part $2=$2 does not make sense. Are you trying to append the first field to the second? – unxnut Sep 14 '13 at 21:07
  • @unxnut, this is not $2=$2 but $2=$2" "$i which is quite different. In any case, $2=$2 sometimes makes sense too with awk. – jlliagre Sep 14 '13 at 21:33
  • That is what I had inferred in my comment above. Trying to append the first field to the second. – unxnut Sep 14 '13 at 23:35
  • It is no trying to append the first field to the second but succeeding in appending the fourth, fifth, sixth fields etc to the second. – jlliagre Sep 15 '13 at 0:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.