我有一个名为 Presidents.txt 的文件。里面的内容如下...
First Last Age Years
Geogre W 57 8.0
John A 61 4.0
Thomas J 57 8.0
James M 57 8.0
Andrew J 61 8.0
我需要的是一个程序,可以添加每位总统的年龄和年数。例如,乔治 W 为 57+8.0,约翰 A 为 61+4.0,依此类推。将每位总统的数字相加后,程序将输出数字最大的总统的名字。例如,此处的输出应为“Andrew J at 69”。到目前为止,我可以一次为每位总统执行此操作,但我希望使用 awk 循环完成此操作。到目前为止我一直使用的命令是
awk 'NR==2 {print $3+$4}' presidents.txt
这会将数字 61 和 4.0 相加,得到输出 65,我认为这是一个开始。我确信我需要使用循环和数组,但不知道从哪里开始,因为我对 Unix 或一般编码没有太多经验。任何帮助表示赞赏。
答案1
假设当 $3+$4 存在重复结果时,您只希望打印输入中最后一次出现的此类结果:
$ cat tst.awk
NR>1 {
curYear = $3 + $4
if ( curYear >= maxYear ) {
maxName = $1 OFS $2
maxYear = curYear
}
}
END {
print maxName, "at", maxYear
}
$ awk -f tst.awk file
Andrew J at 69
例如,给定这个修改后的输入文件,其中 2 个人 (Andrew J
和Sheila E
) 现在的 $3+$4 总价值均为 69:
$ cat file
First Last Age Years
Geogre W 57 8.0
John A 61 4.0
Thomas J 57 8.0
James M 57 8.0
Andrew J 61 8.0
Sheila E 65 4.0
通过上面的脚本,我们得到最后一个输出:
$ awk -f tst.awk file
Sheila E at 69
而也许你想要第一个:
$ cat tst.awk
NR>1 {
curYear = $3 + $4
if ( curYear > maxYear ) {
maxName = $1 OFS $2
maxYear = curYear
}
}
END {
print maxName, "at", maxYear
}
$ awk -f tst.awk file
Andrew J at 69
或全部:
$ cat tst.awk
NR>1 {
curYear = $3 + $4
if ( curYear >= maxYear ) {
if ( curYear > maxYear ) {
numNames = 0
}
maxNames[++numNames] = $1 OFS $2
maxYear = curYear
}
}
END {
for ( nameNr=1; nameNr<=numNames; nameNr++ ) {
print maxNames[nameNr], "at", maxYear
}
}
$ awk -f tst.awk file
Andrew J at 69
Sheila E at 69
答案2
结合awk
和sort
:
awk '{print $1,$2,"at",$3+$4}' file | sort -k4nr | head -1
Andrew J at 69
我们创建一个中间文件,将年龄和年份的总和作为最后一个字段,然后sort
使用k
最后一个4
字段、n
数字和r
反向,最后只打印第一行head
。
这是一项改进,用于涵盖多个具有最大年份的行的情况。我们将它们全部打印出来:
awk '{print $1,$2,"at",$3+$4}' file | sort -k4nr | uniq -f3 --group | sed '/^$/q'
uniq
正在对重复的行进行分组(忽略第一个3
f
字段,这意味着仅测试最后一个数字),用空行分隔各组,并且仅在第一个空行处sed
打印第一组。q
答案3
您甚至不需要任何循环或数组来完成这项工作。尝试:
awk '
{ name= $1 OFS $2 OFS "at" OFS }
NR>1 { age=$3+$4 }
age>ageMax { ageMax=age; data=name; next }
age==ageMax { data= data ageMax ORS name }
END{ print data ageMax }' infile
记录名字和姓氏部分以
{ name= $1 OFS $2 OFS "at" OFS }
供将来处理。跳过标题行并将“年龄”添加到“年份”中
NR>1{ age=$3+$4 }
。如果“age”值大于“ageMax”,则用“age”值更新“ageMax”的值,并用“name”更新“data”
age>ageMax { ageMax=age; data=name; next }
;该next
语句告诉 awk 跳过处理当前行的其余代码,awk 将读取下一行进行处理。如果我们发现相等的最大 AgeMax 值,则通过将 附加到“数据”值来保留所有这些值
age==ageMax { data= data ageMax ORS name }
。如果您不需要全部,只需删除这部分代码,然后它将返回具有最高ageMax的第一条记录,或者替换age>ageMax
为age>=ageMax
返回具有最高ageMax的最后一条记录。在 处
END{ print data ageMax }
,我们打印结果。