ファイル内の異なる文字の数をカウントするにはどうすればよいですか?


19

ファイル内の異なる文字の数を出力するプログラムが必要です。例:

> stats testfile
' ': 207
'e': 186
'n': 102

これを行うツールはありますか?

回答:


21

以下が機能するはずです。

$ sed 's/\(.\)/\1\n/g' text.txt | sort | uniq -c

まず、すべての文字の後に改行を挿入し、各文字をそれぞれの行に配置します。次に、ソートします。次に、uniqコマンドを使用して重複を削除し、各行の先頭にその文字の出現回数を付けます。

リストを頻度でソートするには、これをすべてにパイプしsort -nrます。


4
Mac OS Xのsedではsed 's/\(.\)/\1\'$'\n/g' text.txt
mb21

非常に素晴らしいですが、残念ながら、テキストにUnicode(utf8)文字が含まれていると正しく動作しません。これをsed行う方法はあるかもしれませんが、Jacob VlijmのPythonソリューションはうまく機能しました。
bitinerant

14

スティーブンのソリューションは、優れたシンプルなソリューションです。ソート手順のため、非常に大きなファイル(RAMの約半分に快適に収まらないファイル)のパフォーマンスはそれほど高くありません。これがawkバージョンです。それはいくつかの特殊文字(改行、のために正しいことを行うためにしようとするので、それはまた、もう少し複雑です'\:)。

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/:/'

同じ原則に基づいたPerlソリューションを次に示します。Perlには、内部でソートできるという利点があります。また、ファイルが改行文字で終わっていない場合、これは余分な改行を正しくカウントしません。

perl -ne '
  ++$c{$_} foreach split //;
  END { printf "'\''%s'\'': %d\n", /[\\'\'']/ ? "\\$_" : /./ ? $_ : "\\n", $c{$_}
        foreach (sort {$c{$b} <=> $c{$a}} keys %c) }'

1
その恐ろしい並べ替えを行わなかったための+1
Sparr

1

ルビーを使用した、低速ですが比較的メモリに優しいバージョン。入力サイズに関係なく、約12 MBのRAM。

# 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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.