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 34
编写
awk
脚本来查找没有销售的月份。
我们是否需要一个包含所有月份名称的数组,并且必须使用它来检查它array[$1]
?我试过了,但语法总是搞乱。
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;
}
}'
这是我到目前为止尝试过的方法。我一直收到错误消息:
awk: cmd. line:8: END blocks must have an action part
答案1
我思考我知道你的意思 - 但可以大大简化
通过标准输入管道输入 12 个月的名称,并将它们用作数组的索引
读取月度销售文件,删除我们看到的每个月
打印最后剩下的月份
诀窍是使用-
特殊的文件名来告诉 awk 按照什么顺序读取标准输入和文件,并NR==FNR
作为我们是否正在读取的测试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
April
请注意,您不需要为数组元素分配值 - 只需分配索引就足以定义数组。
或者,您可以在块中定义数组BEGIN
:
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.txt
以下是几种可选的 KISS 方法:
(1)在一个块中创建一个按月份索引的数组BEGIN
,为元素分配值,然后在一个块中迭代该数组END
并打印任何值为零的元素。
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.txt
或者(2)从文件中动态创建数组sales.txt
,然后遍历END
块中的所有月份并打印任何缺失的索引
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