Si los archivos están ordenados (están en su ejemplo):
comm -23 file1 file2
-23
suprime las líneas que están en ambos archivos, o solo en el archivo 2. Si los archivos no están ordenados, canalícelos a través de sort
primero...
Ver la página man aquí
¡ay al rescate!
Esta solución no requiere entradas ordenadas. Primero debe proporcionar el archivo B.
awk 'NR==FNR{a[$0];next} !($0 in a)' fileB fileA
regresa
A
C
¿Cómo funciona?
NR==FNR{a[$0];next}
modismo es para almacenar el primer archivo en una matriz asociativa como claves para una posterior prueba de "contiene".
NR==FNR
está comprobando si estamos escaneando el primer archivo, donde el contador de línea global (NR) es igual al contador de línea de archivo actual (FNR).
a[$0]
agrega la línea actual a la matriz asociativa como clave, tenga en cuenta que esto se comporta como un conjunto, donde no habrá valores duplicados (claves)
!($0 in a)
ahora estamos en los siguientes archivos, in
es una prueba de contenido, aquí está comprobando si la línea actual está en el conjunto que completamos en el primer paso del primer archivo, !
niega la condición. Lo que falta aquí es la acción, que por defecto es {print}
y por lo general no se escribe explícitamente.
Tenga en cuenta que esto ahora se puede usar para eliminar palabras de la lista negra.
$ awk '...' badwords allwords > goodwords
con un ligero cambio, puede limpiar múltiples listas y crear versiones limpias.
$ awk 'NR==FNR{a[$0];next} !($0 in a){print > FILENAME".clean"}' bad file1 file2 file3 ...
Otra forma de hacer lo mismo (también requiere entrada ordenada):
join -v 1 fileA fileB
En Bash, si los archivos no están ordenados previamente:
join -v 1 <(sort fileA) <(sort fileB)
grep -Fvxf <lines-to-remove> <all-lines>
- funciona en archivos no ordenados (a diferencia de
comm
) - mantiene el orden
- es POSIX
Ejemplo:
cat <<EOF > A
b
1
a
0
01
b
1
EOF
cat <<EOF > B
0
1
EOF
grep -Fvxf B A
Salida:
b
a
01
b
Explicación:
-F
:use cadenas literales en lugar del BRE predeterminado-x
:solo considere coincidencias que coincidan con la línea completa-v
:imprimir no coincidentes-f file
:toma patrones del archivo dado
Este método es más lento en archivos preordenados que otros métodos, ya que es más general. Si la velocidad también es importante, consulte:¿Forma rápida de encontrar líneas en un archivo que no están en otro?
Aquí hay una automatización bash rápida para la operación en línea:
remove-lines() (
remove_lines="$1"
all_lines="$2"
tmp_file="$(mktemp)"
grep -Fvxf "$remove_lines" "$all_lines" > "$tmp_file"
mv "$tmp_file" "$all_lines"
)
GitHub ascendente.
uso:
remove-lines lines-to-remove remove-from-this-file
Consulte también:https://unix.stackexchange.com/questions/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another