Si votre objectif est de trouver des lignes communes ou inhabituelles, ce comm
serait ma commande préférée ici.
Il compare deux fichiers et affiche, sur trois colonnes, des lignes qui sont uniques au fichier 1, des lignes qui sont uniques au fichier 2 et des lignes qui apparaissent dans les deux fichiers, respectivement. Vous pouvez lui passer des drapeaux pour supprimer également l'une de ces sorties. Par exemple comm -1 file1 file2
, supprimera la première colonne, les choses uniques à file1. comm -12 file1 file2
ne montrerait que les choses dans les deux fichiers.
Il y a une grosse mise en garde: l'entrée doit être triée. Nous pouvons contourner cela.
Cela vous montrera tout en abc qui n'est pas en mno:
comm -23 <(sort abc.txt) <(sort mno.txt)
Et vous pouvez le canaliser wc -l
pour obtenir un compte.
La raison pour laquelle j'y vais comm
est qu'une fois les fichiers triés, la comparaison côte à côte est très simple sur le plan des calculs. Si vous en traitez des millions, cela fera une différence.
Cela peut être démontré avec quelques fichiers fictifs. J'ai un ordinateur assez rapide, donc pour montrer la différence entre les approches, j'ai besoin d'un jeu d'échantillons assez gigantesque. Je suis passé à 10 millions de chaînes de 10 caractères par fichier.
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > abc.txt
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > mno.txt
$ time comm -23 <(sort abc.txt) <(sort mno.txt) | wc -l
... 0m10.653s
$ time grep -Fcxv -f abc.txt mno.txt
... 0m23.920s
$ time grep -Fcwv -f abc.txt mno.txt
... 0m40.313s
$ time awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt mno.txt | wc -l
... 0m12.161s
Le tri est ce qui prend la plupart du temps dans le mien. Si nous prétendons que abc.txt est statique, nous pouvons le pré-trier et cela rend les comparaisons futures beaucoup plus rapides:
$ sort abc.txt abc-sorted.txt
$ time comm -23 abc-sorted.txt <(sort mno.txt) | wc -l
... 0m7.426s
Vous pouvez les regarder et considérer que quelques secondes ne sont pas pertinentes, mais je dois souligner qu'elles fonctionnent sur une machine haut de gamme. Si vous souhaitez le faire sur un (par exemple) Raspberry Pi 3, vous envisagerez des délais d'exécution beaucoup plus lents et la différence augmentera au point où cela compte vraiment.
grep -cxvFf abc.txt mno.txt
?fgrep
, lesegrep
suppléants sont censés être obsolètes (en faveur degrep -F
,grep -E
- bien que je ne sois pas sûr que quiconque pense qu'ils s'en iront un jour-x
lors de l'utilisation-F
?abcdef
devrait-il compter comme une correspondance ou une non-correspondance avecabcd
?Nous pourrions utiliser awk pour faire le travail en passant deux fichiers, d'abord le fichier de signatures, puis le fichier que nous voulons vérifier. Lorsque nous lisons le premier fichier, nous le savons
NR==FNR
et à ce moment-là, nous pouvons lire les lignes dans le tableau. LorsqueNR!=FNR
nous vérifions si le tableau pour une telle ligne est défini.Inversement, nous pouvons annuler le motif pour imprimer les lignes qui ne sont pas en
abc.txt
Et si nous voulons imprimer le nombre de ceux que nous pouvons employer
sort
etwc
:la source
abc.txt
-mno.txt
qui est{xyz, pqrs}
.Si l'une des listes de mots n'est pas triée, il serait plus rapide d'utiliser une structure de données d'ensemble efficace pour mémoriser les mots courants.
Python
Usage:
Python (plus efficace)
Si vous souhaitez économiser un peu de mémoire pour le stockage intermédiaire et le temps d'exécution, vous pouvez utiliser ce programme légèrement plus difficile à comprendre:
Performance
Étant donné
abc.txt
etmno.txt
avec 1 mio de lignes non triées de 10 caractères ASCII aléatoires chacun (voir la réponse d'Oli pour la configuration):contre.
total: 23 secondes
la source