unix - crear - copiar archivos en linux
Encontrar líneas de un archivo que no están presentes en otro archivo (4)
Esta pregunta ya tiene una respuesta aquí:
Tengo dos archivos (digamos a.txt
y b.txt
), ambos con una lista de nombres. Ya he ejecutado sort
en ambos archivos.
Ahora quiero encontrar líneas de a.txt
que no están presentes en b.txt
.
(Pasé mucho tiempo buscando la respuesta a esta pregunta, por lo que la documentaré para futuras referencias)
El comando que debes usar no es diff
sino comm
comm -23 a.txt b.txt
De manera predeterminada, comm
emite 3 columnas: left-only , right-only , both . Los interruptores -1
, -2
y -3
suprimen estas columnas.
Por lo tanto, -23
oculta solo la derecha y ambas columnas, mostrando las líneas que aparecen solo en el primer archivo (izquierda).
Si desea buscar líneas que aparezcan en ambas, puede usar -12
, que oculta las columnas de solo izquierda y derecha , dejándole solo las dos columnas.
En el caso de que los archivos no se hayan ordenado aún, puede usar:
comm -23 <(sort a.txt) <(sort b.txt)
La respuesta simple no funcionó para mí porque no me di cuenta de que comm
coincide línea por línea, por lo que las líneas duplicadas en un archivo se imprimirán como no existentes en el otro. Por ejemplo, si el archivo 1 contiene:
Alex
Bill
Fred
Y el archivo2 contenía:
Alex
Bill
Bill
Bill
Fred
Entonces comm -13 file1 file2
daría salida:
Bill
Bill
En mi caso, solo quería saber que cada cadena del archivo2 existía en el archivo 1, independientemente de cuántas veces esa línea ocurriera en cada archivo.
Solución 1: use la bandera -u
(única) para sort
:
comm -13 <(sort -u file1) <(sort -u file2)
Solución 2: (la primera respuesta "operativa" que encontré) de unix.stackexchange :
fgrep -v -f file1 file2
Tenga en cuenta que si el archivo2 contiene líneas duplicadas que no existen en el fgrep
1, fgrep
generará cada una de las líneas duplicadas. También tenga en cuenta que mis pruebas totalmente no científicas en una sola computadora portátil para un solo conjunto de datos (bastante grande) mostraron que la Solución 1 (usando comm
) es casi 5 veces más rápida que la Solución 2 (usando fgrep
).
No estoy seguro de por qué se ha dicho que diff
no debe usarse. Lo usaría para comparar los dos archivos y luego solo dar salida a las líneas que están en el archivo de la izquierda pero no en la correcta. Tales líneas están marcadas por diff con <
por lo que basta con grep ese símbolo al comienzo de la línea
diff a.txt b.txt | grep /^/<