awk打印每个类别的所有最小值
希望根据$1和$3组合打印所有最小值。如果有两条或多条线路可用 对于具有唯一组合$1和$3的最小值,则需要打印所有行。例如,$1-“Abc”,最小值$3-“10”出现两次,即Abc,yyy,10,aaa和Abc,ttt,10,aaa。输入文件未按任何顺序排序 Input.txtawk打印每个类别的所有最小值,awk,Awk,希望根据$1和$3组合打印所有最小值。如果有两条或多条线路可用 对于具有唯一组合$1和$3的最小值,则需要打印所有行。例如,$1-“Abc”,最小值$3-“10”出现两次,即Abc,yyy,10,aaa和Abc,ttt,10,aaa。输入文件未按任何顺序排序 Input.txt Country,Desc,Amount,Details Abc,xxx,20,aaa Abc,yyy,10,aaa ghi,ttt,25,ccc Abc,zzz,35,aaa def,xxx,30,bbb Abc,ttt
Country,Desc,Amount,Details
Abc,xxx,20,aaa
Abc,yyy,10,aaa
ghi,ttt,25,ccc
Abc,zzz,35,aaa
def,xxx,30,bbb
Abc,ttt,10,aaa
def,yyy,20,bbb
ghi,yyy,25,ccc
def,zzz,45,bbb
ghi,xxx,35,ccc
ghi,zzz,50,ccc
要将输出与标题行一起打印NR==1,{print}
所需输出.txt
Country,Desc,Amount,Details
Abc,yyy,10,aaa
Abc,ttt,10,aaa
ghi,ttt,25,ccc
ghi,yyy,25,ccc
def,yyy,20,bbb
我使用两个命令来获得所需的输出,第一个是基于$1和$3对输入文件进行排序,第二个是命令awk-F'!看到[$1]+'
寻找您的建议,只需像一行一样。一个awk,它可以处理文件两次。第一次运行时,它为每1美元选择最小的3美元,第二次运行时,它打印最小的:
$ awk '
BEGIN{FS=","} # delimiter
NR==FNR { # first run
if ($1 in a==0 || $3<a[$1])
a[$1]=$3
next
}
$3==a[$1] # || FNR==1 # if Country is data not header
' file file # uncomment the FNR==1
Country,Desc,Amount,Details
Abc,yyy,10,aaa
ghi,ttt,25,ccc
Abc,ttt,10,aaa
def,yyy,20,bbb
ghi,yyy,25,ccc
$awk'
开始{FS=“,”}#分隔符
NR==FNR{#首次运行
如果a==0 | |$3中的($1),如果希望输出与相同的输入文件具有相同的顺序,请尝试以下操作:
awk -F, 'NR==1{print;} FNR>1 && FNR==NR{a[$1]=a[$1]>$3?$3:(a[$1]?a[$1]:$3);next} $3==a[$1]' Input_file Input_file
编辑:现在也添加一个非线性形式的解决方案
awk -F, 'NR==1{
print;
}
FNR>1 && FNR==NR{
a[$1]=a[$1]>$3?$3:(a[$1]?a[$1]:$3);
next
}
$3==a[$1]
' Input_file Input_file
EDIT2:添加一个只读取输入文件1次的解决方案
awk -F, 'FNR==1{
print;
next
}
FNR>1{
a[$1]=a[$1]>$3?$3:(a[$1]?a[$1]:$3);
b[$0]=$0
}
END {;
for(i in b){
split(b[i], array,",");
if(array[3]==a[array[1]]){
print b[i]
}
};
}
' Input_file
如果需要排序输出,则需要将整个文件存储在内存中(或使用排序
)
您可以使用ruby:
ruby -r csv -e 'mins=Hash.new(2**999)
data=Hash.new()
options={:col_sep=>",", :headers=>true, :return_headers=>true}
data=CSV.parse($<, options).map { |r| mins[r[0]]=r[2].to_i < mins[r[0]] ? r[2].to_i : mins[r[0]]; r }
puts data.shift
data.sort_by { |r| r[0] }.each { |r| if mins[r[0]]==r[2].to_i then puts r end }
' file
Country,Desc,Amount,Details
Abc,yyy,10,aaa
Abc,ttt,10,aaa
def,xxx,10,bbb
ghi,yyy,25,ccc
ghi,ttt,25,ccc
使用gawk
您也可以编写一个简单的排序来对任何键进行排序。这是一个非常好的工作。非常感谢James BrownThanks的精彩演讲13
$ gawk -F"," 'FNR==1{header=$0; next}
{lines[FNR-1]=$0
if ($1 in mins==0 || $3<mins[$1])
mins[$1]=$3
}
END{ asort(lines)
print header
for (e in lines) {
split(lines[e], arr, ",")
if (mins[arr[1]]==arr[3]) print lines[e]
}
}
' file
# same output