Outil sous unix pour soustraire des fichiers texte?


16

J'ai un grand fichier composé de champs de texte séparés par des points-virgules sous la forme d'un grand tableau. Il a été trié. J'ai un fichier plus petit composé des mêmes champs de texte. À un moment donné, quelqu'un a concaténé ce fichier avec d'autres, puis a fait un tri pour former le gros fichier décrit ci-dessus. Je voudrais soustraire les lignes du petit fichier du gros (c'est-à-dire pour chaque ligne du petit fichier, si une chaîne correspondante existe dans le gros fichier, supprimez cette ligne dans le gros fichier).

Le fichier ressemble à peu près à ceci

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

Existe-t-il un moyen rapide et élégant de le faire ou dois-je utiliser awk?

Réponses:


28

Vous pouvez utiliser grep. Donnez-lui le petit fichier en entrée et dites-lui de trouver les lignes qui ne correspondent pas:

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

Les options utilisées sont:

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

Nice, a parfaitement fonctionné. Merci beaucoup.
— Escher

1
C'est cool que cela ait fonctionné, mais il me semble que cela aurait été mieux avec l' -xoption également, au cas où une ligne dans le fichier plus petit m'est arrivée une sous-chaîne d'une autre ligne dans le fichier principal. De plus, il est tout à fait possible que la réponse de @ UlrichSchwarz soit plus rapide.
— rici

18

comm est votre ami:

NAME comm - compare deux fichiers triés ligne par ligne

SYNOPSIS comm [OPTION] ... FILE1 FILE2

DESCRIPTION Comparez les fichiers triés FILE1 et FILE2 ligne par ligne.

   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)

( commaura probablement un avantage de performance surgrep car il tient compte du tri.)

Par exemple:

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

2
Bon point sur l'utilisation de comm sur grep pour les listes triées. Ce serait une meilleure réponse si vous donniez un exemple de ligne de commande spécifique tel quecomm -1 -3 file.txt bigfile.txt > newbigfile.txt
— Steve Midgley

Je confirme que j'ai essayé la commande grep indiquée ci-dessus avec des fichiers d'environ 100 Mo et que j'ai eu une erreur "tué". Essayer avec comm s'est terminé avec succès.
— Gianluca Casati

La redirection de commandes est utile pour les fichiers non triés ou si vous avez besoin de plus de deux fichiers:comm -1 -3 <(sort BAD.txt GOOD.txt) <(sort FILES.txt)
— odinho - Velmont
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.