Utilisez une liste de mots pour grep dans une autre liste

8

J'ai une liste de 250 lignes. Je dois les exécuter tous via un serveur Web pour obtenir une liste de sortie. Cette liste, cependant, renvoie beaucoup plus de lignes que ce qui m'intéresse. Disons que ma list.txtest:

a.1
b.1
etc

alors la sortie est output.txt:

a.1 a b c
a.2 b a b
a.3 d k o
b.1 b o p
b.2 o i y
b.3 p i y
etc

Est-il possible d'utiliser la commande grep pour rechercher tous les mots dans list.txt dans le fichier output.txt et ensuite générer "la liste souhaitée" want.txt? J'ai besoin de la ligne entière dans mon output.txt Je suis nouveau dans les scripts, mais ce que j'aimerais, c'est quelque chose comme

grep list.txt output.txt > wanted.txt

Je n'ai pas pu trouver d'exemples de cela

Ditte
la source
Sont-ils tous les deux classés par ordre alphabétique comme vos exemples?
Oli
Non, j'ai un ordre non alphabétique spécifique dans mon list.txt, mais le output.txt est alphabétique, mais j'aimerais qu'il ne contienne que les "hits" pour mon list.txt dans le même ordre non alphabétique
Ditte

Réponses:

11

J'ignorerais greppour celui-ci. C'est bon pour les expressions régulières, mais il ne semble pas que vous en ayez vraiment besoin ici. commpeut comparer deux fichiers et vous montrer des intersections. En utilisant vos exemples exacts:

$ comm -12 list.txt output.txt 
a.1
b.1
etc

C'est plus rapide que n'importe quel grep mais cela dépend (fortement) des fichiers en cours de tri. S'ils ne le sont pas, vous pouvez les pré-trier, mais cela modifiera la sortie afin qu'elle soit également triée.

comm -12 <(sort list.txt) <(sort output.txt) 

Alternativement, cette réponse de iiSeymour vous permettra de le faire avec grep. Les drapeaux demandent un fichier d'entrée et forcent une recherche à mot fixe sur une chaîne fixe. Cela ne dépendra pas de la commande mais sera basé sur la output.txtcommande. Inversez les fichiers si vous les souhaitez dans l'ordre du list.txt.

$ grep -wFf list.txt output.txt 
a.1
b.1
etc

Si votre list.txtest vraiment grand, vous pourriez avoir à aborder ce un peu plus itérativement et passer chaque ligne à grep séparément. Cela augmentera considérablement le temps de traitement. Dans ce qui précède, vous output.txtlirez une fois, mais de cette façon, vous le lirez et le traiterez pour chaque ligne list.txt. C'est horrible ... Mais c'est peut-être votre seul choix. À la hausse, il trie ensuite les choses par list.txtordre.

$ while read line; do grep -wF "$line" output.txt; done < list.txt
a.1
b.1
etc
Oli
la source
1
C'est vraiment intelligent! Quelle est la raison du -12?
Ditte
3
-1supprime les lignes uniques au premier fichier, -2supprime les lignes uniques au second fichier et -3supprime les lignes communes aux deux. Pour obtenir juste les lignes communes, nous supprimons donc les uniques -12.
Oli
agréable! Je pense que je vais utiliser la commande comm. Et puis quand je veux trier le output.txt pour avoir le même ordre que list.txt, je vais juste utiliser la comm -12 <(sort list.txt) <(sort output.txt) après?
Ditte
La commande comm ne m'a pas donné la ligne entière dans le result.txt (et j'ai besoin de tout cela pour obtenir les informations à partir de là). Mais si j'essaye la commande grep, il me demande avec grep: out of memory. Est-ce à dire que c'est trop gros?
Ditte
le 2ème exemple a une redirection STDIN redondante que le shell signalerait comme une erreur. soit créer des fichiers temporaires ou utiliser un fd supplémentaire avec un tri en arrière-plan (délicat dans la plupart des shells) ... il s'agit plus d'une question de programmation mieux posée sur Stack Overflow . personnellement, je le ferais en python.
Skaperen