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?
$ tr ' ' '\n' < FILE | grep Word | wc -l
Où 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\>'
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
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.
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:
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
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.
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
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