2

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?

3
  • Are you sure it's infile| rather than cat infile|?
    – Joseph R.
    Commented Sep 14, 2013 at 20:53
  • @JosephR:You are right.I just wanted to highlight the part that I don't understand
    – Jim
    Commented Sep 14, 2013 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
    Commented Sep 14, 2013 at 21:13

3 Answers 3

4

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

awk '
{
 f=$1
 $1=""
 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.

Edit:

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.

3
  • 1
    Even simpler: {$1 = sprintf("%4d", $1); print} (or "%-4s" as in the original)
    – rici
    Commented Sep 14, 2013 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
    Commented Sep 15, 2013 at 1:05
  • @rici ;-) . . . . . .
    – jlliagre
    Commented Sep 15, 2013 at 1:08
2

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

printf

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.

Example

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

Example

$ 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.

2

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.

5
  • I figured this.But what is the for loop doing?
    – Jim
    Commented Sep 14, 2013 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
    Commented Sep 14, 2013 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
    Commented Sep 14, 2013 at 21:33
  • That is what I had inferred in my comment above. Trying to append the first field to the second.
    – unxnut
    Commented Sep 14, 2013 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
    Commented Sep 15, 2013 at 0:32

You must log in to answer this question.

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