2014-09-03 6 views
9

ich zwei Dateien wie unten (Kreuzung)Linux Kombinieren Sie zwei Dateien, die von Spalte

ID  Name Telephone  
1  John  011 
2  Sam  013 
3  Jena  014 
4  Peter 015 

Zweite Datei Test2.txt

1  Test1 Test2 
2  Test3 Test4 
3  Test5 Test6 
4  Test7 Test8 
5  Test7 Test8 
6  Test7 Test8 
7  Test7 Test8 
8  Test7 Test8 
9  Test7 Test8 

Dann Endergebnis zu kombinieren versuchen

ID  Name Telephone Remark1 Remark2 
1  John 011  Test1 Test2 
2  Sam  013  Test3 Test4 
3  Jena 014  Test5 Test6 
4  Peter 015  Test7 Test8 

Ich mochte das wie unten,

awk -F"\t" ' 
    {key = $1 } 
    NR == 1 {header = key} 
    !(key in result) {result[key] = $0; next} 
    { for (i=2; i <= NF; i++) result[key] = result[key] FS $i } 
    END { 
     print result[header] 
     delete result[header] 
     PROCINFO["sorted_in"] = "@ind_str_asc"  
     for (key in result) print result[key] 
    } 
' Test1.txt Test2.txt > result.txt 

Und ich merke gerade, dass dies Union. Einschließlich aller Daten Test1 und Test2.

Ich möchte nur für Überschneidung Fall zeigen, wie das, was ich erwartete Ergebnis. (1, 2, 3, 4) nur

Haben Sie Jungs eine Idee? Vielen Dank!

Antwort

5
$ awk -v OFS='\t' ' 
NR==1 { print $0, "Remark1", "Remark2"; next } 
NR==FNR { a[$1]=$0; next } 
$1 in a { print a[$1], $2, $3 } 
' Test1.txt Test2.txt 
ID  Name Telephone Remark1 Remark2 
1  John  011  Test1 Test2 
2  Sam  013  Test3 Test4 
3  Jena  014  Test5 Test6 
4  Peter 015  Test7 Test8 
+1

Das ist natürlich die richtige Antwort. – ghoti

17

Es ist viel einfacher, den join Befehl zu verwenden:

$ cat a.txt 
ID  Name Telephone  
1  John  011 
2  Sam  013 
3  Jena  014 
4  Peter 015 
$ cat b.txt 
ID  Remark1 Remark2  
1  Test1 Test2 
2  Test3 Test4 
3  Test5 Test6 
4  Test7 Test8 
5  Test7 Test8 
6  Test7 Test8 
7  Test7 Test8 
8  Test7 Test8 
9  Test7 Test8 
$ join a.txt b.txt 
ID Name Telephone Remark1 Remark2 
1 John 011 Test1 Test2 
2 Sam 013 Test3 Test4 
3 Jena 014 Test5 Test6 
4 Peter 015 Test7 Test8 

Verwenden Sie den column Befehl, um es recht zu drucken:

$ join a.txt b.txt | column -t 
ID Name Telephone Remark1 Remark2 
1 John 011  Test1 Test2 
2 Sam 013  Test3 Test4 
3 Jena 014  Test5 Test6 
4 Peter 015  Test7 Test8 
+4

'join' ist das richtige Werkzeug, aber Vorsicht, dass die Sortierreihenfolge von' sort' verwendet und von 'join' ist nicht genau das gleiche. Am besten ist 'env LANG = en_EN sort ...' und 'env LANG = en_UN join ...'. Ein frustrierendes Problem. Weitere Informationen finden Sie unter http://unix.stackexchange.com/questions/12942/join-file-2-not-in-sorted-order –

+0

, wenn ich versuche, mit meinem Fall richtig verbunden, aber tab-getrennte ist verschwunden. Und wenn ich eine Spalte verwende -t sieht aus wie ein gebrochenes Format. –

+2

@ clear.choi, 't $ '\ t' file1 file2' –

2

Eine weitere Alternative wäre pr sein, die für die Formatierung von Dateien zum Drucken verwendet wird, .

$ pr -tm -w 50 Test1.txt Test2.txt 
ID  Name Telephone ID Remark1 Remark2 
1  John  011  1 Test1 Test2 
2  Sam  013  2 Test3 Test4 
3  Jena  014  3 Test5 Test6 
4  Peter  015  4 Test7 Test8 
         5 Test7 Test8 
         6 Test7 Test8 
         7 Test7 Test8 
         8 Test7 Test8 
         9 Test7 Test8 

Das wichtigste ist die m Flag, welche Dateien in Spalten übergeht. Das Flag t entfernt Kopf- und Fußzeilen - da wir nicht auf Papier drucken, brauchen wir sie nicht. Das letzte w Flag dient zum Einstellen der Breite.

1
awk -F"\t" ' 
    {key = $1 FS $2 FS $3 FS $4} 
    NR == 1 {header = key} 
    !(key in result) {result[key] = $0; next} 
    { for (i=5; i <= NF; i++) result[key] = result[key] FS $i } 
    END { 
     print result[header] 
     delete result[header] 
     PROCINFO["sorted_in"] = "@ind_str_asc" # if using GNU awk 
     for (key in result) print result[key] 
    } 
' Test1.txt Test2.txt ... > result.txt