Comment trouver le nombre de mots multiples dans un fichier texte?

Je suis capable de trouver le nombre de fois qu’un mot apparaît dans un fichier texte comme sous Linux, nous pouvons utiliser

cat filename|grep -c tom 

Ma question est de savoir comment trouver le nombre de mots multiples tels que “tom” et “joe” dans un fichier texte.

Puisque vous avez un couple de noms, les expressions régulières sont la voie à suivre pour celle-ci. Au début, je pensais que c’était aussi simple qu’un simple compte grep sur l’expression régulière de joe ou tom, mais que cela ne tenait pas compte du scénario où Tom et Joe sont sur la même ligne (ou Tom et Tom d’ailleurs) .

test.txt:

 tom is really really cool! joe for the win! tom is actually lame. $ grep -c '\< \(tom\|joe\)\>' test.txt 2 

Comme vous pouvez le voir sur le fichier test.txt, 2 est la mauvaise réponse. Nous devions donc tenir compte des noms figurant sur la même ligne.

J’ai ensuite utilisé grep -o pour afficher uniquement la partie d’une ligne correspondante qui correspond au modèle où il donnait les correspondances correctes de tom ou de joe dans le fichier. J’ai ensuite canalisé les résultats en nombre de lignes dans wc pour le nombre de lignes.

 $ grep -o '\(joe\|tom\)' test.txt|wc -l 3 

3 … la bonne réponse! J’espère que cela t’aides

Ok, donc d’abord diviser le fichier en mots, puis sort et uniq :

 tr -cs '[:alnum:]' '\n' < testdata | sort | uniq -c 

Vous utilisez uniq :

 sort filename | uniq -c 

Utilisez awk:

 {for (i=1;i< =NF;i++) count[$i]++ } END { for (i in count) print count[i], i } 

Cela produira un compte de fréquence de mots complet pour l'entrée. Pipe la sortie à grep pour obtenir les champs souhaités

 awk -f w.awk input | grep -E 'tom|joe' 

BTW, vous n'avez pas besoin de cat dans votre exemple, la plupart des programmes qui agissent comme des filtres peuvent prendre le nom de fichier comme paramètre; il est donc préférable d'utiliser

 grep -c tom filename 

Si ce n'est pas le cas, il y a une forte possibilité que les gens commencent à vous lancer une utilisation inutile du Cat Award 😉

  1. L’échantillon que vous avez donné ne recherche pas les mots “tom”. Il comptera “atome” et “bas” et beaucoup plus.
  2. Grep recherche des expressions régulières . L’expression régulière qui correspond au mot “tom” ou “joe” est

     \< \(tom\|joe\)\> 

Vous pourriez faire regexp,

  cat filename |tr ' ' '\n' |grep -c -e "\(joe\|tom\)" 

En est un:

 cat txt | tr -s '[:punct:][:space:][:blank:]'| tr '[:punct:][:space:][:blank:]' '\n\n\n' | tr -s '\n' | sort | uniq -c 

METTRE À JOUR

Une solution de script shell:

 #!/bin/bash file_name="$2" ssortingng="$1" if [ $# -ne 2 ] then echo "Usage: $0  " exit 1 fi if [ ! -f "$file_name" ] then echo "file \"$file_name\" does not exist, or is not a regular file" exit 2 fi line_no_list=("") curr_line_indx=1 line_no_indx=0 total_occurance=0 # line_no_list contains loc k the line number loc k+1 the number # of times the ssortingng occur at that line while read line do flag=0 while [[ "$line" == *$ssortingng* ]] do flag=1 line_no_list[line_no_indx]=$curr_line_indx line_no_list[line_no_indx+1]=$((line_no_list[line_no_indx+1]+1)) total_occurance=$((total_occurance+1)) # remove the pattern "$ssortingng" with a null" and recheck line=${line/"$ssortingng"/} done # if we have entered the while loop then increment the # line index to access the next array pos in the next # iteration if (( flag == 1 )) then line_no_indx=$((line_no_indx+2)) fi curr_line_indx=$((curr_line_indx+1)) done < "$file_name" echo -e "\nThe string \"$string\" occurs \"$total_occurance\" times" echo -e "The string \"$string\" occurs in \"$((line_no_indx/2))\" lines" echo "[Occurence # : Line Number : Nos of Occurance in this line]: " for ((i=0; i 

J’ai complètement oublié grep -f:

 cat filename | grep -fc names 

Solution AWK:

En supposant que les noms sont dans un fichier appelé names :

 cat filename | awk 'NR==FNR {h[NR] = $1;ct[i] = 0; cnt=NR} NR !=FNR {for(i=1;i< =cnt;++i) if(match($0,h[i])!=0) ++ct[i] } END {for(i in h) print h[i], ct[i]}' names - 

Notez que votre grep d'origine ne recherche pas de mots. par exemple

 $ echo tomorrow | grep -c tom 1 

Vous avez besoin de grep -w

 gawk -vRS='[^[:alpha:]]+' '{print}' | grep -c '^(tom|joe|bob|sue)$' 

Le programme gawk définit le séparateur d’enregistrements sur tout élément non alphabétique, de sorte que chaque mot se retrouvera sur une ligne distincte. Ensuite, grep compte les lignes qui correspondent à l’un des mots que vous voulez exactement.

Nous utilisons gawk car le awk POSIX n’autorise pas le séparateur d’enregistrement regex.

Pour faire court, vous pouvez remplacer '{print}' par 1 – de toute façon, c’est un programme Awk qui imprime simplement tous les enregistrements d’entrée (“est-ce que 1 est vrai? C’est alors l’action par défaut, {print} .” )

Pour trouver tous les hits dans toutes les lignes

 echo "tom is really really cool! joe for the win! tom is actually lame." | akw '{i+=gsub(/tom|joe/,"")} END {print i}' 3 

Cela comptera “tomtom” comme 2 hits.