awk打印每个类别的所有三个唯一最小值 - 续

时间:2017-08-17 14:10:15

标签: awk

希望根据每个类别的$1 and $3组合打印所有三个最小值。 例如$1-"abc"具有唯一的三个最小值$3 - "5,10,15",输入文件未按任何顺序排序。 寻找你的建议。

INPUT.TXT

Country,Desc,Amount,Details
abc,xxx,20,aaa
abc,yyy,10,aaa
ghi,ttt,25,ccc
abc,zzz,5,aaa
def,xxx,10,bbb
abc,ttt,15,aaa
def,yyy,20,bbb
ghi,yyy,25,ccc
def,zzz,30,bbb
abc,sss,5,aaa
ghi,zzz,50,ccc
def,zzz,45,bbb
abc,mmm,5,aaa
ghi,xxx,35,ccc
abc,nnn,5,aaa
ghi,xxx,60,ccc

想要打印输出以及标题行NR==1 , {print}

Desired Output.txt

Country,Desc,Amount,Details
abc,zzz,5,aaa
abc,sss,5,aaa
abc,mmm,5,aaa
abc,nnn,5,aaa
abc,yyy,10,aaa
abc,ttt,15,aaa
def,xxx,10,bbb
def,yyy,20,bbb
def,zzz,30,bbb
ghi,ttt,25,ccc
ghi,yyy,25,ccc
ghi,xxx,35,ccc
ghi,zzz,50,ccc

编辑#1:

也想打印最低订单。确定每个类别的第一个最小值,第二个最小值,第三个最小值。

所需输出#1:

Country,Desc,Amount,Details,Min_Order
abc,mmm,5,aaa,1
abc,nnn,5,aaa,1
abc,sss,5,aaa,1
abc,zzz,5,aaa,1
abc,yyy,10,aaa,2
abc,ttt,15,aaa,3
def,xxx,10,bbb,1
def,yyy,20,bbb,2
def,zzz,30,bbb,3
ghi,ttt,25,ccc,1
ghi,yyy,25,ccc,1
ghi,xxx,35,ccc,2
ghi,zzz,50,ccc,3

编辑#2:

我试过这样的

{ read -r header; echo "$header"","Min_Order; sort -t, -k1,1 -k3,3n; } < Input.csv | awk -F, '
    $1 != prev1 {num_seen = 0; prev3 = -999}
    $3 != prev3 {num_seen++}
    num_seen <= 3 {print $0","num_seen}
    {prev1 = $1; prev3 = $3}
' > Output.csv

并获得 输出#2:

Country,Desc,Amount,Details,Min_Order,1
abc,mmm,5,aaa,1
abc,nnn,5,aaa,1
abc,sss,5,aaa,1
abc,zzz,5,aaa,1
abc,yyy,10,aaa,2
abc,ttt,15,aaa,3
def,xxx,10,bbb,1
def,yyy,20,bbb,2
def,zzz,30,bbb,3
ghi,ttt,25,ccc,1
ghi,yyy,25,ccc,1
ghi,xxx,35,ccc,2
ghi,zzz,50,ccc,3

请建议您避免在标题行中添加一个其他列,以便将标题从Country,Desc,Amount,Details,Min_Order,1打印到Country,Desc,Amount,Details,Min_Order

2 个答案:

答案 0 :(得分:1)

我会先对文件进行排序。这将使awk过程更容易。

{ read -r header; echo "$header"; sort -t, -k1,1 -k3,3n; } < file | awk -F, '
    $1 != prev1 {num_seen = 0; prev3 = -999}
    $3 != prev3 {num_seen++}
    num_seen <= 3 {print}
    {prev1 = $1; prev3 = $3}
'
Country,Desc,Amount,Details
abc,mmm,5,aaa
abc,nnn,5,aaa
abc,sss,5,aaa
abc,zzz,5,aaa
abc,yyy,10,aaa
abc,ttt,15,aaa
def,xxx,10,bbb
def,yyy,20,bbb
def,zzz,30,bbb
ghi,ttt,25,ccc
ghi,yyy,25,ccc
ghi,xxx,35,ccc
ghi,zzz,50,ccc

答案 1 :(得分:1)

我可以建议你一个简单的解决方案。在此之前,在第3列(即金额)中,它始终是保持固定长度的更好方法(特别是如果它是一个数字,并且您希望根据列进行排序)。所以我假设这里金额将有2位数。这样,5将成为05(因为我修正了金额的长度)。

cat file

输入将具有:

abc,xxx,20,aaa
abc,yyy,10,aaa
ghi,ttt,25,ccc
abc,zzz,05,aaa
def,xxx,10,bbb
abc,ttt,15,aaa
def,yyy,20,bbb
ghi,yyy,25,ccc
def,zzz,30,bbb
abc,sss,05,aaa
ghi,zzz,50,ccc
def,zzz,45,bbb
abc,mmm,05,aaa
ghi,xxx,35,ccc
abc,nnn,05,aaa
ghi,xxx,60,ccc

现在,对此进行排序的最简单方法是:

sort -t, -b  -k1.1,1.3 -k3.1,3.2 file

它将打印(将是您的第一个预期输出):

abc,mmm,05,aaa
abc,nnn,05,aaa
abc,sss,05,aaa
abc,zzz,05,aaa
abc,yyy,10,aaa
abc,ttt,15,aaa
abc,xxx,20,aaa
def,xxx,10,bbb
def,yyy,20,bbb
def,zzz,30,bbb
def,zzz,45,bbb
ghi,ttt,25,ccc
ghi,yyy,25,ccc
ghi,xxx,35,ccc
ghi,zzz,50,ccc
ghi,xxx,60,ccc

awk的帮助下,您可以实现第二次输出。

sort -t, -b  -k1.1,1.3 -k3.1,3.2 file | awk -F, '{OFS=","};{if(a[$1]!=$3){a[$1]=$3;cnt[$1]++}else if(!a[$1]){cnt[$1]=1}{print $0","cnt[$1]}}'

它将打印:

abc,mmm,05,aaa,1
abc,nnn,05,aaa,1
abc,sss,05,aaa,1
abc,zzz,05,aaa,1
abc,yyy,10,aaa,2
abc,ttt,15,aaa,3
abc,xxx,20,aaa,4
def,xxx,10,bbb,1
def,yyy,20,bbb,2
def,zzz,30,bbb,3
def,zzz,45,bbb,4
ghi,ttt,25,ccc,1
ghi,yyy,25,ccc,1
ghi,xxx,35,ccc,2
ghi,zzz,50,ccc,3
ghi,xxx,60,ccc,4

我希望你在等待更好的解决方案。 :)

如果您想添加标题:

sed -i '1i Country,Desc,Amount,Details,Min_Order' output