Assignment in braces vs outside braces in awk

awk

From this question, I answer with this solution:

awk 'FNR==NR{a[FNR]=$2;next}{$NF=a[FNR]}1' file2 file1

It works as expected.

But the first solution I thought is:

$ awk 'FNR==NR{a[FNR]=$2;next}$NF=a[FNR]' file2 file1
A 63 9 6
B 45 3 5

It does not work, since when awk had not print the first line in file1. It make me suprise, and don't know why awk skip the first line.

Here is some examples:

$ awk 'FNR==NR{next}$1=123' file2 file1 
123 23 8 T
123 63 9 9
123 45 3 J  

$ awk 'FNR==NR{a[FNR]=$2;next} FNR in a' file2 file1
A   23  8   T
A   63  9   9
B   45  3   J

You can see, from both examples, awk works as expected. First assigning new value to a field of current record affected record value, and awk print new value. The second show that awk had process all record in file2, no record is skipped.

Why awk skip the first line in my first solution?

I use gawk 4.0.1, and also tested with mawk 1.3.3.

Best Answer

You have:

$NF=a[FNR]

as the final condition (the one that determines whether to print). Assignments return the value assigned, in this case a[FNR]. The first line of the data file from the linked question is:

A   0

a[FNR] is initialised to $2. That means the value of a[FNR] is 0, which is a false value to awk. That means the assignment is false, which makes the conditional false and suppresses the default printing behaviour. If we change the data file to:

A   1
A   6   
B   0

then the first line will be printed, but the last one will be missing.

So it's not that the first line is absent, it's any line where the last field is zero (or empty). It just happens that the first line and only the first line was like that.

Related Question