Strumento in unix per sottrarre file di testo?


16

Ho un file di grandi dimensioni composto da campi di testo separati da punti e virgola sotto forma di una tabella di grandi dimensioni. È stato ordinato. Ho un file più piccolo composto dagli stessi campi di testo. Ad un certo punto, qualcuno ha concatenato questo file con altri e poi ha fatto una specie per formare il file di grandi dimensioni sopra descritto. Vorrei sottrarre le righe del file piccolo da quello grande (cioè per ogni riga nel file piccolo, se esiste una stringa corrispondente nel file grande, eliminare quella riga nel file grande).

Il file appare più o meno così

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

eccetera

Esiste un modo rapido ed elegante per farlo o devo usare awk?

Risposte:


28

È possibile utilizzare grep. Dagli il piccolo file come input e digli di trovare linee non corrispondenti:

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

Le opzioni utilizzate sono:

   -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.)

Bello, ha funzionato perfettamente. Grazie mille.
Escher,

1
È bello che abbia funzionato, ma mi sembra che sarebbe stato meglio anche con l' -xopzione, nel caso in cui una riga nel file più piccolo mi fosse capitato di creare una sottostringa di un'altra riga nel file principale. Inoltre, è del tutto possibile che la risposta di @ UlrichSchwarz sia più veloce.
rici,

18

comm È tuo amico:

NAME comm - confronta due file ordinati riga per riga

SINOSSI comm [OPZIONE] ... FILE1 FILE2

DESCRIZIONE Confronta i file ordinati FILE1 e FILE2 riga per riga.

   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)

( commprobabilmente avrà un vantaggio in termini di prestazioni greppoiché tiene conto dell'ordinamento.)

Per esempio:

comm -1 -3 file.txt bigfile.txt > newbigfile.txt

2
Un buon punto sull'uso di comm over grep per elenchi ordinati. Questa sarebbe una risposta migliore se fornissi un esempio specifico della riga di comando comecomm -1 -3 file.txt bigfile.txt > newbigfile.txt
Steve Midgley,

Confermo di aver provato il comando grep riportato sopra con file di circa 100 MB e ho riscontrato un errore "ucciso". Provare con comm è finito con successo.
Gianluca Casati,

Il reindirizzamento dei comandi è utile per file non ordinati o se sono necessari più di due file:comm -1 -3 <(sort BAD.txt GOOD.txt) <(sort FILES.txt)
odinho - Velmont
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.