find tous les mots dans un file text apparaissant dans un autre file text

Supposons que j'ai deux files a.txt et b.txt . Je veux find tous les mots dans a.txt qui apparaissent dans b.txt .

Existe-t-il une command spécifique pour le faire?

Avec bash , zsh et certaines implémentations de ksh :

 comm -12 <(tr -s '[:space:]' '[\n*]' < a.txt | sort -u) \ <(tr -s '[:space:]' '[\n*]' < b.txt | sort -u) 

Là, le mot est une séquence de caractère sans espacement (attention à GNU tr , cela ne fonctionne pas avec des caractères d'espacement multi-octets).

comm trouve les lignes communes entre deux files sortingés. Sans options, il imprime 3 colonnes: les lignes uniquement dans le file1, les lignes uniquement dans le file2 et les lignes communes aux deux. Vous ajoutez -1 , -2 , -3 pour supprimer les colonnes correspondantes de la sortie. Donc comm -12 ne quitte que la troisième colonne (les lignes communes).

tr -s '[:space:]' '[\n*]' permet de classr chaque caractère de l' space de class en newlines, pour mettre chaque mot sur sa propre ligne.

sort -u sortinge et supprime les duplicates de la sortie de tr .

La substitution de process <(...) canalise les sorties des commands tr|sort à comm .


Avec zsh :

 w1=($(<a.txt)) w2=($(<b.txt)) print -rl -- ${(u)${w1:*w2}} 

Là, le mot est une séquence de caractères autres que l'espace, l'onglet, le nul et le saut de ligne (avec la valeur par défaut de $IFS ).

$(<a.txt) est une version optimisée de $(cat a.txt)zsh lit le contenu du file sans invoquer cat , puisqu'il n'est pas cité, il subit un fractionnement de mots (mais pas de globes contrairement aux autres shells ).

Donc w1 et w2 sont des arrays contenant tous les mots dans a.txt et b.txt .

${w1:*w2} est un opérateur zsh qui donne l'intersection de deux arrays (les éléments communs aux deux). (u) est un indicateur d'expansion de paramètre qui conserve des éléments uniques (supprime les duplicates).

print -rl imprime chaque argument un par ligne.

 # Create dummy text file containing two words $ echo -e "overflow\ngrep" > b # Search in file for lines containing one word from file b $ grep --color --fixed-ssortingngs --file b /usr/share/dict/words 

Résultat sur mon système:

 overflow overflow's overflowed overflowing overflows 

Ajoutez le paramètre –only-matching (-o) pour get uniquement les mots et non la ligne entière dans laquelle ils apparaissent.

En supposant que les mots dans les files sont séparés par LF et que les mots ne contiennent que des caractères "gentils" et qu'il n'y a pas de LF dans le file b.txt,

 egrep `tr '\n' '|' < b.txt` a.txt 

pourrait faire l'affaire.

Bien que vous ne travailliez pas au niveau des mots, il vous serait plus utile de travailler sur les lignes pour vous ou quelqu'un d'autre à la search d'une réponse.

 diff --left-column --from-file=a.txt --to-file=b.txt 

Compare le file a.txt au file b.txt ne produisant que des lignes communes.