awk commands using array
Andrew Henderson
Month Sales
January 20
February 30
March 43
February 34
January 12
June 89
May 97
June 60
July 23
August 13
August 45
October 56
October 45
November 34Write an
awkscript to find the months with no sales.
Do we need to have an array containing the names of all the months and do we have to check it with array[$1]? I tried that but I keep messing up the syntax.
echo 'January
February
March
April
May
June
July
August
September
October
November
December' |
awk '
BEGIN{ flag=0;}
{arr[month++]=$0}
{ sales[$1]+=$2;
}
END
{ for(month in arr) { if(month in sales) flag=1; if(flag==0) print month; }
}'This is what I've tried so far. I keep getting an error saying:
awk: cmd. line:8: END blocks must have an action part 2 1 Answer
I think I can see where you're going with this - but it can be simplified quite a lot
pipe in the names of the 12 months via standard input and use them as indices of an array
read the file of monthly sales, deleting each month as we see it
print whatever months remain at the end
The trick is to use - as a special filename to tell awk which order to read the standard input and the file, and NR==FNR as a test for whether we are reading stdin:
printf '%s\n' January February March April May \ June July August September October November December | awk ' NR==FNR {sales[$1]; next} {delete sales[$1]} END {for(m in sales) print m} ' - sales.txt
December
September
AprilNote that you don't need to assign values to the array elements - just assigning indices is sufficient to define the array.
Alternatively, you could define the array in a BEGIN block:
awk ' BEGIN { sales["January"]; sales["February"]; sales["March"]; sales["April"]; sales["May"]; sales["June"]; sales["July"]; sales["August"]; sales["September"]; sales["October"]; sales["November"]; sales["December"]; } {delete sales[$1]} END { for(m in sales) print m }' sales.txtA couple of alternative KISS approaches:
(1) create an array indexed by months in a BEGIN block, assign values to the elements, then iterate over the array in an END block and print any whose value is zero
awk ' BEGIN { sales["January"]; sales["February"]; sales["March"]; sales["April"]; sales["May"]; sales["June"]; sales["July"]; sales["August"]; sales["September"]; sales["October"]; sales["November"]; sales["December"]; } NR > 1 { sales[$1] += $2; } END { for (m in sales) { if (sales[m] == 0) print m; } }
' sales.txtor (2) create the array on the fly from the sales.txt file, then iterate over all the months in an END block and print any missing indices
awk ' NR > 1 { sales[$1] += $2 } END { n = split("January February March April May June July August September October November December", months); for (i=1;i<=n;i++) { if (!(months[i] in sales)) print months[i] } }
' sales.txt