2016-03-30 6 views
0

Ich suche Tabellen mit 2 oder mehr Dateien des Formats zu machen:Normalizate Dateien mit beitreten

05/2003 3 
06/2003 2 
07/2003 1 
09/2003 2 
10/2003 2 
11/2003 2 
12/2003 1 
01/2004 2 
02/2004 1 
04/2004 2 

und

01/2003 2 
02/2003 2 
07/2003 1 
08/2003 1 
09/2003 1 
01/2004 2 
06/2004 1 
09/2004 2 
10/2004 1 
02/2005 3 

ich die Zeile benötigen, die in einer Datei sind aber nicht in der andere, die mit 0 in das Feld der Datei eingefügt wird, die nicht die Zeile enthält (es können mehr als 2 Dateien erstellt werden). Das "Join" -Programm tut dies nicht. Wenn ich die Option "-a" verwende, werden alle Zeilen gedruckt, aber die Spaltennummer bleibt erhalten. Die Option "-e" hilft auch nicht. Die Ausgabe sollte in diesem Format sein:

01/2003 0 2 
02/2003 0 2 
05/2003 3 0 
06/2003 0 2 
07/2003 1 1 
08/2003 0 1 
09/2003 2 1 
10/2003 2 0 
11/2003 2 0 
12/2003 1 0 
01/2004 2 2 
02/2004 1 0 
04/2004 2 0 
06/2004 0 1 
09/2004 0 2 
10/2004 0 1 
02/2005 0 3 

Seit jetzt, danke!

Bonus: Wenn ich in Zukunft die Quelle des "Join" -Befehls modifiziere, um dies zu tun, könnte es kanonisiert werden?

+0

Dies sieht aus wie ein Problem besser geeignet für SQL "innere Verbindung", aber eine einfache, so kann mit Awk oder Bash möglich sein. –

+0

Sie können drei disjunkte Mengen verketten (nur Datei1, Datei1 und Datei2, nur Datei3), die durch 'Join' mit einer Textbearbeitung erzeugt werden können, um die fehlenden Werte hinzuzufügen, aber ich sehe keine triviale Lösung. Besser zur vollen Leistung von 'awk' zurückkehren. – karakfa

Antwort

0

awk zur Rettung! mit Art Hilfe ...

$ awk 'NR==FNR{a[$1]=$2;f=0;next} 
     ($1 in a){f=a[$1]; delete a[$1]} 
       {print $1,f,$2; f=0} 
      END{for(k in a) print k,a[k],0}' file1 file2 | 
    sort -k1.4n -k1.1,1.2n 

01/2003 0 2 
02/2003 0 2 
05/2003 3 0 
06/2003 2 0 
07/2003 1 1 
08/2003 0 1 
09/2003 2 1 
10/2003 2 0 
11/2003 2 0 
12/2003 1 0 
01/2004 2 2 
02/2004 1 0 
04/2004 2 0 
06/2004 0 1 
09/2004 0 2 
10/2004 0 1 
02/2005 0 3 

awk zur Rettung! wieder sollte dies mit einer beliebigen Anzahl von Dateien arbeiten, aber ich habe nicht mehr als 2.

$ awk 'FNR==1{c++} {a[$1,c]=$2;keys[$1]} 
      END{for(k in keys) 
       {printf "%s", k; 
       for(i=1;i<=c;i++) 
        printf "%s", FS (((k,i) in a)?a[k,i]:0); 
       print ""}} ' file1 file2 | 
    sort -k1.4n -k1.1,1.2 

01/2003 0 2 
02/2003 0 2 
05/2003 3 0 
06/2003 2 0 
07/2003 1 1 
08/2003 0 1 
09/2003 2 1 
10/2003 2 0 
11/2003 2 0 
12/2003 1 0 
01/2004 2 2 
02/2004 1 0 
04/2004 2 0 
06/2004 0 1 
09/2004 0 2 
10/2004 0 1 
02/2005 0 3 
+0

Vielen Dank. Es ist eine großartige Lösung, aber ich kann es nicht für 3 Dateien verwenden, auch wenn ich in zwei und nach dem dritten benutze. – Learner

0
awk 'FNR==1{n++} 
    { 
    a[$1"@"n]=$2; 
    b[$1] 
    } 
END { 
    for (i in b) { 
     printf i; 
     for (x=1;x<=n;x++){ 
      if (i"@"x in a){ 
       printf " "a[i"@"x] 
      } 
      else{ 
       printf " 0" 
      } 
     }; 
    print "" 
    } 
}' file1 file2| sort -n -k2,1 -t/ 

Zum Zählen Sie die Dateinummer Zähler n verwendet wird (FNR ==1) getestet. Array a mit Index als $1"@"n erstellt und zugewiesen Wert von $2 (a[$1"@"n]=$2) und Array b mit Index als $1 wird auch erstellt.

Im END: Iterate durch das Array b (for (i in b)) und für alle Dateien (for (x=1;x<=n;x++)) print $2 dh Wert in a wenn der i"@"x Index in a else print ist 0.

Dann sortieren sie basiert am Datum (sort -n -k2,1 -t/)