2017-08-12 1 views
3

Möchten Sie alle Mindestwerte basierend auf $ 1 und $ 3 Kombinationen drucken. Wenn zwei oder mehr Zeilen verfügbar sind, müssen für den Minimalwert mit eindeutigen Kombinationen von $ 1 und $ 3 alle Zeilen drucken. Zum Beispiel erscheint $ 1- "Abc" mit einem Minimalwert von $ 3- "10" zweimal, d. H. Abc, yyy, 10, aaa und Abc, ttt, 10, aaa. Die Eingabedatei wurde in keiner Reihenfolge sortiert.awk, um alle Mindestwerte für jede Kategorie zu drucken

Eingabe.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 

Möchten Sie die Ausgabe drucken zusammen mit Kopfzeile NR==1 , {print}

Wunsch 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 

Ich bin mit zwei Befehle, um die gewünschte Ausgabe zu erhalten , zuerst sort die Eingabedatei basierend auf $ 1 und $ 3 dann zweiter Befehl awk -F, '!seen[$1]++' Suche nach Ihre Vorschläge, einfach einen Liner zu mögen.

Antwort

4

Ein awk, der die Datei zweimal verarbeitet. Im ersten Lauf nimmt es die kleinste 1 $ 3 für jede $ und auf der zweiten druckt er das kleinste:

$ 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

Das ist eine sehr süße awk. – dawg

+1

Vielen Dank James Brown – VNA

1

Wenn Sie die Ausgabe in derselben Sequenz wollen wie gleiche input_file dann versuchen, zu folgenden:

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 

EDIT: Hinzufügen einer nicht-Liner Form der Lösung auch jetzt.

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: das Hinzufügen einer weiteren Lösung, in der wir input_file nur 1 mal gelesen.

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

Vielen Dank RavinderSingh13 – VNA

0

Wenn Sie sortierte Ausgabe wollen, müssen Sie die gesamte Datei in den Speicher haben (oder verwenden Sie sort).

können Sie Rubin verwenden:

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 

In diesem Fall von Country sortiert, aber man konnte auf ein beliebiges Feld der csv sortieren.

Sie können auch gawk verwenden, wenn Sie eine sortierte Version wollen:

$ 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 

Mit gawk Sie könnten eine triviale Art schreiben als auch auf die Schlüssel zu sortieren.

+1

Vielen Dank Dawg !!! – VNA

Verwandte Themen