2017-08-12 31 views
3

想要打印基於$ 1和$ 3組合的所有最小值。如果有兩行或更多行可用 作爲具有$ 1和$ 3的唯一組合的最小值,則需要打印所有行。例如,具有出現兩次的最小值$ 3-「10」的$ 1-「Abc」,即Abc,yyy,10,aaa和Abc,ttt,10,aaa。輸入文件未按任何順序排序。awk打印每個類別的所有最小值

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}

期望Output.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 

我用兩個命令來獲得所需的輸出,第一個sort基於$ 1和$ 3的輸入文件,然後是第二個命令awk -F, '!seen[$1]++' 尋找你的建議只是像一個班輪。

回答

4

一個處理文件兩次的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 
+1

這是一個非常甜蜜的awk。 – dawg

+1

非常感謝James Brown – VNA

1

如果你想在同一順序輸出相同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 

編輯:現在也添加一個非線性的解決方案。

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:添加中,我們讀INPUT_FILE只有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 
+1

非常感謝RavinderSingh13 – VNA

0

如果要排序輸出,則需要在內存中的整個文件(或使用sort)。

您可以使用紅寶石:

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 

在這種情況下,由Country排序,但你可以排序的CSV的任何領域。

$ 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 

隨着gawk你可以寫一個簡單的排序排序上的任意鍵,以及:

您還可以,如果你想有一個排序的版本使用gawk

+1

非常感謝! – VNA