Réponses:
Les éléments suivants devraient fonctionner:
$ sed 's/\(.\)/\1\n/g' text.txt | sort | uniq -c
Tout d'abord, nous insérons une nouvelle ligne après chaque caractère, en mettant chaque caractère sur sa propre ligne. Ensuite, nous le trions. Ensuite, nous utilisons la commande uniq pour supprimer les doublons, en préfixant chaque ligne avec le nombre d'occurrences de ce caractère.
Pour trier la liste par fréquence, canalisez tout cela dans sort -nr
.
sed
, mais la solution Python de Jacob Vlijm a bien fonctionné pour moi.
La solution de Steven est bonne et simple. Ce n'est pas si performant pour les très gros fichiers (les fichiers qui ne tiennent pas confortablement dans environ la moitié de votre RAM) en raison de l'étape de tri. Voici une version awk. Il est aussi un peu plus compliqué , car il essaie de faire la bonne chose pour quelques caractères spéciaux (sauts de ligne, '
, \
, :
).
awk '
{for (i=1; i<=length; i++) ++c[substr($0,i,1)]; ++c[RS]}
function chr (x) {return x=="\n" ? "\\n" : x==":" ? "\\072" :
x=="\\" || x=="'\''" ? "\\" x : x}
END {for (x in c) printf "'\''%s'\'': %d\n", chr(x), c[x]}
' | sort -t : -k 2 -r | sed 's/\\072/:/'
Voici une solution Perl sur le même principe. Perl a l'avantage de pouvoir trier en interne. De plus, cela ne comptera pas correctement une nouvelle ligne supplémentaire si le fichier ne se termine pas par un caractère de nouvelle ligne.
perl -ne '
++$c{$_} foreach split //;
END { printf "'\''%s'\'': %d\n", /[\\'\'']/ ? "\\$_" : /./ ? $_ : "\\n", $c{$_}
foreach (sort {$c{$b} <=> $c{$a}} keys %c) }'
Une version lente mais relativement conviviale, utilisant du rubis. Environ une douzaine de Mo de RAM, quelle que soit la taille d'entrée.
# count.rb
ARGF.
each_char.
each_with_object({}) {|e,a| a[e] ||= 0; a[e] += 1}.
each {|i| puts i.join("\t")}
ruby count.rb < input.txt
t 20721
d 20628
S 20844
k 20930
h 20783
... etc
sed 's/\(.\)/\1\'$'\n/g' text.txt