2014-09-03 28 views
9

sto cercando di combinare due file come qui di seguito (intersezione)Linux Unire due file per colonna

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

secondo file 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 

risultato finale Poi

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 

Mi piace quanto segue,

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 

E ho appena notato che questo è un set dell'Unione. Incluso tutti i dati Test1 e Test2.

Mi piacerebbe mostrare solo per caso Intersection come quello che mi aspettavo risultato. (1, 2, 3, 4) solo

Avete qualche idea? Grazie!

risposta

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

Questa è, ovviamente, la risposta giusta. – ghoti

17

è molto più facile da usare il comando join:

$ 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 

Utilizzare il comando column a praticamente stamparlo:

$ 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' è lo strumento giusto, ma attenzione che l'ordinamento utilizzato da' sort' e da 'join' non sono esattamente la stessa cosa. Meglio usare 'env LANG = en_EN sort ...' e 'env LANG = en_UN join ...'. Un problema frustrante. Per ulteriori informazioni, vedere http://unix.stackexchange.com/questions/12942/join-file-2-not-in-sorted-order –

+0

quando provo a farlo correttamente, ma il delimitatore di tabulazione è scomparso. E se uso la colonna -t sembra un formato rotto. –

+2

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

2

Un'altra alternativa sarebbe pr che viene utilizzato per formattazione file per la stampa .

$ 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 

La più importante è la bandiera m, che unisce i file in colonne. Il flag t rimuove le intestazioni e i piè di pagina - dal momento che non stiamo andando a stampare su carta, non ne abbiamo bisogno. L'ultimo flag w è per l'impostazione della larghezza.

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