awk 按多列分组并使用非主键打印最大值
awk group by multiple columns and print max value with non-primary key
我是这个网站的新手,正在尝试学习 awk。我试图找到 field3 的最大值,按 field1 分组并打印所有具有最大值的字段。字段 2 包含时间,这意味着对于每个 item1,字段 2、字段 3 和字段 4
有 96 个值
输入文件:(逗号分隔)
item1,00:15,10,30
item2,00:45,20,45
item2,12:15,30,45
item1,00:30,20,56
item3,23:00,40,44
item1,12:45,50,55
item3,11:15,30,45
期望的输出:
item1,12:45,50,55
item2,12:15,30,45
item3,11:15,30,45
到目前为止我尝试了什么:
BEGIN{
FS=OFS=","}
{
if (a[]<){
a[]=}
}
END{
for (i in a ){
print i,a[i]
}
但这只会打印
item1,50
item2,30
item3,30
但我需要打印相应的 field2 和 field4 以及所需输出中显示的最大值。请帮忙
这里的问题是你没有存储整行,所以当你检查最后的数据时,没有完整的数据要打印。
你需要做的是使用另一个数组,比如 data[index]=full line
:
BEGIN{
FS=OFS=","}
{
if (a[]<){
a[]=
data[]=[=10=]} # store it here!
}
END {
for (i in a )
print data[i] # print it here
}
或作为单线:
$ awk 'BEGIN{FS=OFS=","} {if (a[]<) {a[]=; data[]=[=11=]}} END{for (i in a) print data[i]}' file
item1,12:45,50,55
item2,12:15,30,45
item3,23:00,40,44
在 sort
命令的帮助下:
sort -t, -k1,1 -k3,3nr file | awk -F, '!seen[]++'
要稳健地完成这项工作,您需要:
$ cat tst.awk
BEGIN { FS="," }
!( in max) {
max[] =
data[] = [=10=]
keys[++numKeys] =
}
> max[] {
max[] =
data[] = [=10=]
}
END {
for (keyNr=1; keyNr<=numKeys; keyNr++) {
print data[keys[keyNr]]
}
}
$ awk -f tst.awk file
item1,12:45,50,55
item2,12:15,30,45
item3,23:00,40,44
在进行 min/max 计算时,您应该始终使用读取的第一个值作为 min/max 值的种子,而不是假设它总是小于或大于某个任意值(例如零或-null 如果你跳过上面的 !( in max)
块)。
您需要 keys
数组来在打印输出时保留输入顺序。如果您使用 in
,那么输出顺序将是随机的。
请注意,awk 的惯用语法很简单:
<condition> { <action> }
非 C 风格:
{ if ( <condition> ) { <action> } }
我是这个网站的新手,正在尝试学习 awk。我试图找到 field3 的最大值,按 field1 分组并打印所有具有最大值的字段。字段 2 包含时间,这意味着对于每个 item1,字段 2、字段 3 和字段 4
有 96 个值输入文件:(逗号分隔)
item1,00:15,10,30
item2,00:45,20,45
item2,12:15,30,45
item1,00:30,20,56
item3,23:00,40,44
item1,12:45,50,55
item3,11:15,30,45
期望的输出:
item1,12:45,50,55
item2,12:15,30,45
item3,11:15,30,45
到目前为止我尝试了什么:
BEGIN{
FS=OFS=","}
{
if (a[]<){
a[]=}
}
END{
for (i in a ){
print i,a[i]
}
但这只会打印
item1,50
item2,30
item3,30
但我需要打印相应的 field2 和 field4 以及所需输出中显示的最大值。请帮忙
这里的问题是你没有存储整行,所以当你检查最后的数据时,没有完整的数据要打印。
你需要做的是使用另一个数组,比如 data[index]=full line
:
BEGIN{
FS=OFS=","}
{
if (a[]<){
a[]=
data[]=[=10=]} # store it here!
}
END {
for (i in a )
print data[i] # print it here
}
或作为单线:
$ awk 'BEGIN{FS=OFS=","} {if (a[]<) {a[]=; data[]=[=11=]}} END{for (i in a) print data[i]}' file
item1,12:45,50,55
item2,12:15,30,45
item3,23:00,40,44
在 sort
命令的帮助下:
sort -t, -k1,1 -k3,3nr file | awk -F, '!seen[]++'
要稳健地完成这项工作,您需要:
$ cat tst.awk
BEGIN { FS="," }
!( in max) {
max[] =
data[] = [=10=]
keys[++numKeys] =
}
> max[] {
max[] =
data[] = [=10=]
}
END {
for (keyNr=1; keyNr<=numKeys; keyNr++) {
print data[keys[keyNr]]
}
}
$ awk -f tst.awk file
item1,12:45,50,55
item2,12:15,30,45
item3,23:00,40,44
在进行 min/max 计算时,您应该始终使用读取的第一个值作为 min/max 值的种子,而不是假设它总是小于或大于某个任意值(例如零或-null 如果你跳过上面的 !( in max)
块)。
您需要 keys
数组来在打印输出时保留输入顺序。如果您使用 in
,那么输出顺序将是随机的。
请注意,awk 的惯用语法很简单:
<condition> { <action> }
非 C 风格:
{ if ( <condition> ) { <action> } }