"Ungrep" - quels modèles ne correspondent pas


13

Je recherche une commande ou un script pour effectuer les opérations suivantes - étant donné:

file1.txt:

abcd
efgh 
ijkl
mnop

file2.txt:

123abcd123
123efgh123
123mnop123

Je veux une commande qui fait quelque chose comme ceci:

ungrep file1.txt file2.txt

et renvoie ce qui suit:

ijkl

En d'autres termes, cela me donne les lignes dans file1.txt qui ne retourneront aucun résultat sur une grep de file2.txt. Je sais que je peux le faire en itérant via file1.txt, en accueillant file2.txt pour chaque ligne et en stockant le résultat, et en affichant toutes les lignes où le résultat est vide, mais j'espérais un moyen plus efficace de le faire.

Réponses:


18

Avec GNU, greples éléments suivants devraient fonctionner. En utilisant l' -foption, passez file1.txtcomme un "fichier de signatures" - mais passez-le également une seconde fois comme fichier de données. Utilisez -opour signaler uniquement les pièces correspondantes. Extrait enfin les mots qui ne correspondent qu'une seule fois - ceux-ci correspondent aux lignes file1.txtqui ne trouvent pas de correspondance dans file2.txt.

grep -h -o -f  file1.txt file2.txt file1.txt | sort | uniq -u
ijkl

Très bonne description. Merci et +1.
unxnut

4
Vous pourriez obtenir le même effet sans l'astuce grep:, sort file1.txt <(grep -of file1.txt file2.txt) | uniq -umais, comme votre solution, cela ne fonctionne que lorsque le fichier de motif ne contient en fait aucun métacaractère regex.
rici

@rici, c'est un très bon point
iruvar

2
Amélioration:grep -oFf file1.txt file2.txt | sort file1.txt - | uniq -u
Stéphane Chazelas

10

Vous pouvez le faire avec awkcomme:

awk '
  NR == FNR {w[$0]; next}
  {for (i in w) if (index($0,i)) delete w[i]}
  END {for (i in w) print i}' file1.txt file2.txt

En utilisant index, nous recherchons des sous-chaînes plutôt que des correspondances d'expressions régulières.

Parce que nous supprimons le mot du tableau dès que nous trouvons une correspondance, nous évitons les recherches inutiles.


1
Je n'accepterais que celui-ci. Il n'invoque aucun tri O (n log n) et n'échoue pas étrangement lorsque les modèles contiennent des métacaractères d'expression régulière, et pourrait être étendu pour prendre en charge les expressions régulières.
Kaz

Je ne peux pas croire que simplement évaluer w[$0]a pour effet secondaire d'ajouter la clé au tableau.
Kaz

1
@Kaz, oui, cela peut être déroutant, et vous trouverez de nombreux scripts qui n'attribuent pas sciemment des éléments de tableau par inadvertance en faisant if (a[$1])au lieu de if ($1 in a)par exemple. C'est le cas de tous, awky compris l'original awket nawk, mais en regardant la norme hier, je n'ai pas pu la trouver spécifiée.
Stéphane Chazelas

1
@Kaz Voici la citation POSIX: "L'application doit garantir qu'un index multidimensionnel utilisé avec l' opérateur in est mis entre parenthèses. L' opérateur in , qui teste l'existence d'un élément de tableau particulier, ne doit pas faire exister cet élément. Tout toute autre référence à un élément de tableau inexistant le créera automatiquement. " Il peut être trouvé en faisant défiler un paragraphe ou deux à partir d' ici .
jw013

1
Tant qu'il file1n'est pas énorme (pour une valeur énorme), je préférerais cette solution car elle ne nécessite aucun tri file2et devrait être beaucoup plus efficace.
jw013
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.