¿Existe alguna herramienta que pueda obtener líneas que contiene el archivo A, pero el archivo B no? Podría hacer un pequeño script simple con, por ejemplo, perl, pero si algo así ya existe, ahorraré mi tiempo de ahora en adelante.
¿Existe alguna herramienta que pueda obtener líneas que contiene el archivo A, pero el archivo B no? Podría hacer un pequeño script simple con, por ejemplo, perl, pero si algo así ya existe, ahorraré mi tiempo de ahora en adelante.
Respuestas:
Si. La grep
herramienta estándar para buscar archivos de cadenas de texto se puede utilizar para restar todas las líneas de un archivo a otro.
grep -F -x -v -f fileB fileA
Esto funciona utilizando cada línea en el archivo B como patrón ( -f fileB
) y tratándola como una cadena simple para que coincida (no una expresión regular regular) ( -F
). Obliga a que la coincidencia ocurra en toda la línea ( -x
) e imprime solo las líneas que no coinciden ( -v
). Por lo tanto, está imprimiendo las líneas en el archivo A que no contienen los mismos datos que cualquier línea en el archivo B.
La desventaja de esta solución es que no tiene en cuenta el orden de las líneas y si su entrada tiene líneas duplicadas en diferentes lugares, es posible que no obtenga lo que espera. La solución a eso es usar una herramienta de comparación real como diff
. Puede hacer esto creando un archivo diff con el valor de contexto en el 100% de las líneas en el archivo, luego analizándolo solo para las líneas que se eliminarían si se convierte el archivo A al archivo B. (Tenga en cuenta que este comando también elimina el diff formateo después de obtener las líneas correctas).
diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC
-u
argumento en minúscula realmente toma un parámetro de un número siempre que no sea seguido por un espacio. La ventaja de la forma en que lo tenía antes es que funcionará con o sin un valor, por lo que podría usar algo en esa rutina de subcomando que no devolvió salida. Mayúscula '-U' por otro lado requiere un argumento.
diff
tubería funciona de maravilla gracias.
grep
que sea necesario. Ejemplo:grep -F -x -v -f <(sort fileB) <(sort fileA)
diff
es que la posición en el archivo se tiene en cuenta.
La respuesta depende en gran medida del tipo y formato de los archivos que está comparando.
Si los archivos que está comparando son archivos de texto ordenados, entonces la herramienta GNU escrita por Richard Stallman y Davide McKenzie llamada comm
puede realizar el filtrado que está buscando. Es parte de los coreutils.
Digamos que tiene los siguientes 2 archivos:
$ cat a
1
2
3
4
5
$ cat b
1
2
3
4
5
6
Líneas en el archivo b
que no están en el archivo a
:
$ comm <(sort a) <(sort b) -3
6
comm
; desafortunadamente, comm
requiere archivos ordenados
<()
? Funciona y lo entiendo, pero ¿hay un nombre para esta rareza?
<()
también se conoce como sustitución de procesos .
comm
originalmente fue escrito alrededor de 1973 por alguien en Bell Labs, no rms. Te refieres a la implementación de GNU que vino mucho después. Ha habido muchas implementaciones diferentes de las utilidades de Unix a lo largo de los años.
de stackoverflow ...
comm -23 archivo1 archivo2
-23 suprime las líneas que están en ambos archivos, o solo en el archivo 2. Los archivos tienen que ser ordenados (están en su ejemplo) pero si no, canalícelos primero por orden ...
Vea la página del manual aquí
Los métodos grep y comm (con clasificación) tardan mucho en archivos grandes. SiegeX y ghostdog74 compartieron dos excelentes métodos awk para extraer líneas exclusivas de uno de los dos archivos en Stack Overflow:
$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
Si los archivos son grandes y no tiene un orden personalizado para sus entradas, grep tarda demasiado. Una alternativa rápida sería
sort file1 > 1
sort file2 > 2
diff 1 2 | grep "\>" | sed -e 's/> //'
[file2-file1 resultados a la pantalla, canalización a archivo, etc.]
Cambiar >
a <
obtendría la resta opuesta.rm 1 2