2011-12-15 20 views
12

A volte ho bisogno di confrontare due file di testo. Ovviamente, diff mostra le differenze, nasconde anche le somiglianze, che è il tipo del punto.* nix: esegue unione unione/intersezione/differenza di elenchi

Supponiamo di voler eseguire altri confronti su questi file: imposta unione, intersezione e sottrazione, trattando ogni riga come un elemento nel set.

Ci sono allo stesso modo semplici utilità comuni o one-liner che possono farlo?


Esempi:

A.txt

john 
mary 

b.txt

adam 
john 

$> set_union a.txt b.txt 
john 
mary 
adam 

$> set_intersection a.txt b.txt 
john 

$> set_difference a.txt b.txt 
mary 
+0

Può fare un esempio di cosa si intende per "unione" qui? – fge

risposta

19

dell'Unione: sort -ufile ...

incrocio: sortfile ...| uniq -d

Difference: sortfile ...| uniq -u

7

Se si desidera ottenere le linee comuni tra le due file, è possibile utilizzare l'utilità comm.

A.txt:

A 
B 
C 

B.txt

A 
B 
D 

e poi, utilizzando comm vi darà:

$ comm <(sort A.txt) <(sort B.txt) 
     A 
     B 
C 
    D 

Nella prima colonna, si dispone di ciò che è nel primo file e non nel secondo.

Nella seconda colonna si ha ciò che si trova nel secondo file e non nel primo.

Nella terza colonna, si dispone di ciò che è in entrambi i file.

0

Se non lo fai mente usando un po 'di Perl, e se le dimensioni del file sono ragionevoli tali da poter essere scritte in un hash, potresti raccogliere file in due hash da fare:

#...get common keys in an array... 
my @both_things 
for (keys %from_1) { 
    push @both_things, $_ if exists $from_2{$_}; 
} 

#...put unique things in an array... 
my @once_only 
for (keys %from_1) { 
    push @once_only, $_ unless exists $from_2($_); 
} 
0

io non posso commentare la risposta di Aaron Digulla, che pur essendo accettato in realtà non calcolare il set difference.

La differenza di set A \ B con gli input forniti deve restituire solo mary, ma la risposta accettata restituisce anche erroneamente adam.

This answer ha un awk one-liner che calcola correttamente la differenza set:

awk 'FNR==NR {a[$0]++; next} !a[$0]' b.txt a.txt