Herramienta en unix para restar archivos de texto?

16

Tengo un archivo grande compuesto por campos de texto separados por punto y coma en forma de una tabla grande. Ha sido ordenado. Tengo un archivo más pequeño compuesto por los mismos campos de texto. En algún momento, alguien concatenó este archivo con otros y luego hizo una ordenación para formar el archivo grande descrito anteriormente. Me gustaría restar las líneas del archivo pequeño del archivo grande (es decir, para cada línea en el archivo pequeño, si existe una cadena coincidente en el archivo grande, elimine esa línea en el archivo grande).

El archivo se ve más o menos así

GenericClass1; 1; 2; NA; 3; 4;
GenericClass1; 5; 6; NA; 7; 8;
GenericClass2; 1; 5; NA; 3; 8;
GenericClass2; 2; 6; NA; 4; 1;

etc.

¿Hay una manera rápida y elegante de hacer esto o tengo que usar awk?

Escher
fuente

Respuestas:

28

Puedes usar grep. Dele el archivo pequeño como entrada y dígale que busque líneas que no coincidan:

grep -vxFf file.txt bigfile.txt > newbigfile.txt

Las opciones utilizadas son:

   -F, --fixed-strings
          Interpret PATTERN as a  list  of  fixed  strings,  separated  by
          newlines,  any  of  which is to be matched.  (-F is specified by
          POSIX.)
   -f FILE, --file=FILE
          Obtain  patterns  from  FILE,  one  per  line.   The  empty file
          contains zero patterns, and therefore matches nothing.   (-f  is
          specified by POSIX.)

   -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v
          is specified by POSIX.)
   -x, --line-regexp
          Select only those matches that exactly match the whole line.  
          (-x is specified by POSIX.)
terdon
fuente
Agradable, funcionó perfectamente. Muchas gracias.
Escher
1
Es genial que funcionó, pero me parece que también hubiera sido mejor con la -xopción, en caso de que una línea en el archivo más pequeño me sucediera una subcadena de otra línea en el archivo principal. Además, es bastante posible que la respuesta de @ UlrichSchwarz sea más rápida.
rici
18

comm es tu amigo:

COMUNICACIÓN DE NOMBRE: compara dos archivos ordenados línea por línea

SINOPSIS COM [OPCIÓN] ... ARCHIVO1 ARCHIVO2

DESCRIPCIÓN Compare los archivos ordenados FILE1 y FILE2 línea por línea.

   With  no  options, produce three-column output.  Column one contains lines unique to FILE1, column two contains
   lines unique to FILE2, and column three contains lines common to both files.

   -1     suppress column 1 (lines unique to FILE1)

   -2     suppress column 2 (lines unique to FILE2)

   -3     suppress column 3 (lines that appear in both files)

( commProbablemente tendrá un beneficio de rendimiento, grepya que tiene en cuenta la clasificación).

Por ejemplo:

comm -1 -3 file.txt bigfile.txt > newbigfile.txt
Ulrich Schwarz
fuente
2
Buen punto sobre el uso de comm over grep para listas ordenadas. Esta sería una mejor respuesta si proporcionara un ejemplo de línea de comando específico, comocomm -1 -3 file.txt bigfile.txt > newbigfile.txt
Steve Midgley, el
Confirmo que probé el comando grep mencionado anteriormente con archivos de alrededor de 100 MB y obtuve un error "matado". Intentando con comunicación, terminó con éxito.
Gianluca Casati
La redirección de comandos es útil para archivos sin clasificar o si necesita más de dos archivos:comm -1 -3 <(sort BAD.txt GOOD.txt) <(sort FILES.txt)
odinho - Velmont