web-dev-qa-db-fra.com

Comment puis-je compter le nombre d'occurrences d'un mot dans un fichier texte avec la ligne de commande?

J'ai un gros fichier JSON qui se trouve sur une seule ligne, et je veux utiliser la ligne de commande pour pouvoir compter le nombre d'occurrences d'un mot dans le fichier. Comment puis je faire ça?

45
mythz
$ tr ' ' '\n' < FILE | grep Word | wc -l

tr remplace les espaces par des retours à la ligne, grep filtre toutes les lignes résultantes correspondant à Word et wc compte les autres.

On peut même enregistrer la partie wc en utilisant l'option -c De grep:

$ tr ' ' '\n' < FILE | grep -c Word

L'option -c Est définie par POSIX.

S'il n'est pas garanti qu'il y ait des espaces entre les mots, vous devez utiliser un autre caractère (comme délimiteur) pour le remplacer. Par exemple, les autres pièces tr sont

tr '"' '\n'

ou

tr "'" '\n'

si vous souhaitez remplacer les guillemets doubles ou simples. Bien sûr, vous pouvez également utiliser tr pour remplacer plusieurs caractères à la fois (pensez à différents types d'espaces et de ponctuation).

Dans le cas où vous devez compter Word mais pas prefixWORD, WORDsuffix ou prefixWORDsuffix, vous pouvez inclure le modèle Word dans des marqueurs de début/fin de ligne:

grep -c '^Word$'

Ce qui équivaut à des marqueurs Word-begin/end, dans notre contexte:

grep -c '\<Word\>'
48
maxschlepzig

Avec GNU grep, cela fonctionne: grep -o '\<Word\>' | wc -l

-o Imprime chaque partie correspondante de chaque ligne sur une ligne distincte.

\< Affirme le début d'un mot et \> Affirme la fin d'un mot (semblable au \b De Perl), ce qui garantit que vous ne faites pas correspondre une chaîne dans le au milieu d'un mot.

Par exemple,

$ python -c 'importer ce' | grep '\ <one \>' 
 Il devrait y avoir une- et de préférence uniquement une - Manière évidente de le faire. 
 Les espaces de noms sont une klaxon excellente idée - faisons-en plus! 
$ python -c 'importer ce' | grep -o '\ <one \>' 
uneuneune$ python -c 'importer ce' | grep -o '\ <one \>' | wc -l 
 3 
25
ephemient

Malheureusement cela ne fonctionne pas avec GNU coreutils.

grep -o -c Word file

Si cela fonctionne sur votre plateforme, c'est une solution élégante et assez intuitive; mais les gens GNU pensent encore.

11
tripleee
sed -e 's/[^[:alpha:]]/ /g' text_to_analize.txt | tr '\n' " " |  tr -s " " | tr " " '\n'| tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr | nl 

Cette commande crée les éléments suivants:

  1. Remplacez tous les caractères non alphanumériques par un espace vide.
  2. Tous les sauts de ligne sont également convertis en espaces.
  3. Réduit tous les espaces vides multiples à un seul espace vide
  4. Tous les espaces sont désormais convertis en sauts de ligne. Chaque mot dans une ligne.
  5. Traduit tous les mots en minuscules pour éviter que "Bonjour" et "bonjour" soient des mots différents
  6. Sorts de text
  7. Compte et supprime les lignes égales
  8. Trie l'inverse afin de compter les mots les plus fréquents
  9. Ajoutez un numéro de ligne à chaque mot afin de connaître la posotion du mot dans son ensemble

Par exemple, si je veux analyser le premier message de Linus Torvald:

De: [email protected] (Linus Benedict Torvalds) Groupes de discussion: comp.os.minix Objet: Qu'aimeriez-vous voir le plus dans minix? Résumé: petit sondage pour mon nouveau système d'exploitation Message-ID: <[email protected]> Date: 25 août 91 20:57:08 GMT Organisation: Université d'Helsinki

Bonjour à tous avec Minix -

Je fais un système d'exploitation (gratuit) (juste un passe-temps, ne sera pas grand et professionnel comme GNU) pour 386 (486) AT clones. Cela brasse depuis avril et Je voudrais avoir des commentaires sur les choses que les gens aiment/n'aiment pas dans minix, car mon système d'exploitation y ressemble quelque peu (même disposition physique du système de fichiers (pour des raisons pratiques), entre autres).

J'ai actuellement porté bash (1.08) et gcc (1.40), et les choses semblent fonctionner. Cela implique que j'obtiendrai quelque chose de pratique dans quelques mois, et j'aimerais savoir quelles fonctionnalités la plupart des gens souhaiteraient. Toutes les suggestions sont les bienvenues, mais je ne promets pas de les mettre en œuvre ????

Linus ([email protected])

PS. Oui - il est exempt de tout code minix, et il a un fs multi-thread. Ce n'est PAS protable (utilise 386 changement de tâche, etc.), et il ne supportera probablement jamais autre chose que des disques durs AT, car c'est tout ce que j'ai : .

Je crée un fichier nommé linus.txt , je colle le contenu puis j'écris dans la console:

sed -e 's/[^[:alpha:]]/ /g' linus.txt | tr '\n' " " |  tr -s " " | tr " " '\n'| tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr | nl 

Le résultat serait:

 1        7 i
 2        5 to
 3        5 like
 4        5 it
 5        5 and
 6        4 minix
 7        4 a
 8        3 torvalds
 9        3 of
10        3 helsinki
11        3 fi
12        3 any
13        2 would
14        2 won
15        2 what
16        ...

Si vous souhaitez visualiser uniquement les 20 premiers mots:

sed -e 's/[^[:alpha:]]/ /g' text_to_analize.txt | tr '\n' " " |  tr -s " " | tr " " '\n'| tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr | nl | head -n 20

Il est important de noter que la commande tr 'AZ' 'a-z' ne supporte pas UTF-8 --- (encore , pour que dans les langues étrangères le mot APRÈS soit traduit par aprÈs.

Si vous souhaitez uniquement rechercher l'occurrence d'un mot, vous pouvez ajouter un grep à la fin:

sed -e 's/[^[:alpha:]]/ /g' text_to_analize.txt | tr '\n' " " |  tr -s " " | tr " " '\n'| tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr | nl | grep "\sword_to_search_for$"

Dans un script appelé search_freq :

#!/bin/bash
sed -e 's/[^[:alpha:]]/ /g' text_to_analize.txt | tr '\n' " " |  tr -s " " | tr " " '\n'| tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr | nl | grep "\s$1$"

Le script doit être appelé:

 search_freq Word_to_search_for
7
Roger Borrell

Selon que vous souhaitez faire correspondre le mot dans les clés ou dans les valeurs des données JSON, vous souhaiterez probablement extraire uniquement les clés ou uniquement les valeurs des données. Sinon, vous risquez de compter certains mots trop de fois s'ils apparaissent à la fois comme clés et comme valeurs.

Pour extraire toutes les clés:

jq -r '..|objects|keys[]' <file.json

Ceci teste récursivement si la chose courante est un objet, et si c'est le cas, elle extrait les clés. Le résultat sera une liste de clés, une par ligne.

Pour extraire toutes les valeurs:

jq -r '..|scalars' <file.json

Cela fonctionne de manière similaire, mais comporte moins d'étapes.

Vous pouvez ensuite diriger la sortie de ce qui précède via grep -c 'PATTERN' (pour faire correspondre un modèle avec les clés ou les valeurs) ou grep -c -w -F 'Word' (pour faire correspondre un Word dans les clés ou les valeurs), ou grep -c -x -F 'Word' (pour faire correspondre une clé ou une valeur complète), ou similaire, pour effectuer votre comptage.

3
Kusalananda

J'ai json avec quelque chose comme ça: "number":"OK","number":OK" répété plusieurs fois sur une même ligne.

Mon simple compteur "OK":

sed "s|,|\n|g" response | grep -c OK

0
khazad-dum_miner

En utilisant grep -c vous ne compterez que les lignes, une ligne peut avoir plusieurs occurrences du mot.

Cela le ferait:

grep -o Word foo|wc -l
0
Ramiro Velazquez