Si su objetivo es encontrar líneas comunes o poco comunes, comm
sería mi comando ir aquí.
Compara dos archivos y muestra, en tres columnas, líneas exclusivas del archivo 1, líneas exclusivas del archivo 2 y líneas que aparecen en ambos archivos, respectivamente. Puede pasarle banderas para suprimir cualquiera de estos resultados también. Por ejemplo comm -1 file1 file2
, suprimirá la primera columna, las cosas exclusivas de file1. comm -12 file1 file2
solo mostraría cosas en ambos archivos.
Hay una gran advertencia: la entrada debe ser ordenada. Podemos evitar esto.
Esto le mostrará todo en abc que no está en mno:
comm -23 <(sort abc.txt) <(sort mno.txt)
Y puedes canalizar eso wc -l
para obtener un recuento.
La razón con la que voy comm
es que una vez que los archivos están ordenados, la comparación lado a lado es computacionalmente muy simple. Si está lidiando con millones de estos, eso hará la diferencia.
Esto se puede demostrar con un par de archivos simulados. Tengo una computadora bastante rápida, así que para mostrar la diferencia entre los enfoques, necesito un conjunto de muestras bastante gigantesco. He ido a 10 millones de cadenas de 10 caracteres por archivo.
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > abc.txt
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > mno.txt
$ time comm -23 <(sort abc.txt) <(sort mno.txt) | wc -l
... 0m10.653s
$ time grep -Fcxv -f abc.txt mno.txt
... 0m23.920s
$ time grep -Fcwv -f abc.txt mno.txt
... 0m40.313s
$ time awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt mno.txt | wc -l
... 0m12.161s
La clasificación es lo que lleva la mayor parte del tiempo en el mío. Si pretendemos que abc.txt es estático, podemos ordenarlo previamente y eso hace que las futuras comparaciones sean mucho más rápidas:
$ sort abc.txt abc-sorted.txt
$ time comm -23 abc-sorted.txt <(sort mno.txt) | wc -l
... 0m7.426s
Puede mirar esto y considerar unos segundos irrelevantes, pero debo resaltar que se están ejecutando en una máquina de gama alta. Si quisieras hacer esto en un (por ejemplo) Raspberry Pi 3, verás cambios mucho más lentos y la diferencia aumentará a un punto que realmente importa.
grep -cxvFf abc.txt mno.txt
?fgrep
, lasegrep
alternativas supuestamente están en desuso (a favor degrep -F
,grep -E
aunque no estoy seguro de que alguien crea que alguna vez se irán)-x
cuando se usa-F
?abcdef
debería contar eso como una coincidencia o noabcd
?Podríamos usar awk para hacer el trabajo pasando dos archivos, primero el archivo de patrones y luego el archivo que queremos verificar. Cuando estamos leyendo el primer archivo, sabemos eso
NR==FNR
y en ese momento podemos leer líneas en una matriz. CuandoNR!=FNR
verificamos si se establece la matriz para dicha línea.Por el contrario, podemos negar el patrón para imprimir aquellas líneas que no están en
abc.txt
Y si queremos imprimir el recuento de aquellos que podemos emplear
sort
ywc
:fuente
abc.txt
,mno.txt
que es{xyz, pqrs}
.Si alguna de las listas de palabras no está ordenada, sería más rápido usar una estructura de datos de conjunto eficiente para recordar las palabras comunes.
Pitón
Uso:
Python (más eficiente)
Si desea guardar un poco de memoria para el almacenamiento intermedio y el tiempo de ejecución, puede usar este programa un poco más difícil de entender:
Actuación
Dado
abc.txt
ymno.txt
con 1 millón de líneas sin clasificar de 10 caracteres de dígitos ASCII aleatorios cada una (consulte la respuesta de Oli para la configuración):vs.
total: 23 segundos
fuente