awk打印每个类别的所有最小值

awk打印每个类别的所有最小值,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

希望根据$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,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