perl - teoria - * nix: realizar un conjunto de unión/intersección/diferencia de listas
union de conjuntos (4)
A veces necesito comparar dos archivos de texto. Obviamente, diff
muestra las diferencias, sino que también oculta las similitudes, que es una especie de punto.
Supongamos que quiero hacer otras comparaciones en estos archivos: establecer unión, intersección y resta, tratando cada línea como un elemento en el conjunto.
¿Existen utilidades comunes similares o simples que pueden hacer esto?
Ejemplos:
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
Unión: sort -u
archivos ...
Intersección: sort
archivos ... | uniq -d
| uniq -d
Diferencia: sort
archivos ... | uniq -u
| uniq -u
Si desea obtener las líneas comunes entre dos archivos, puede usar la utilidad de comunicación .
A.txt:
A
B
C
B.txt
A
B
D
y luego, usar comm te dará:
$ comm <(sort A.txt) <(sort B.txt)
A
B
C
D
En la primera columna, tiene lo que está en el primer archivo y no en el segundo.
En la segunda columna, tiene lo que está en el segundo archivo y no en el primero.
En la tercera columna, tiene lo que está en ambos archivos.
Si no le importa usar un poco de Perl, y si los tamaños de sus archivos son razonables, de modo que se puedan escribir en un hash, puede recopilar los archivos en dos hash para hacer:
#...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($_);
}
No puedo comentar la respuesta de Aaron Digulla, que a pesar de ser aceptado no calcula la diferencia establecida .
La diferencia establecida A / B con las entradas dadas solo debe devolver mary
, pero la respuesta aceptada también devuelve adam
incorrectamente.
Esta respuesta tiene un awk one-liner que calcula correctamente la diferencia establecida:
awk ''FNR==NR {a[$0]++; next} !a[$0]'' b.txt a.txt