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.