「語」とか「文字」の頻度を確認してみませんか? 「英文」や「プログラム言語」、それにプログラムで処理した結果などの確認には、とっても役立つ道具です。 思ったような結果になっているか? の確認にも使えますよ。
引数として確認したい「入力ファイル」を指定します。 これだけです。
$ wordfreq.rb ChangeLog | head -15 2229 c 1243 jp 879 Matsumoto 879 Yukihiro 879 matz 867 co 725 netlab 536 2000 488 eval 468 to 464 rb 451 should 423 1999 406 for 369 ruby
$ charfreq.rb ChangeLog | head -15 18142 e 15012 t 14810 o 14186 a 13300 r 12443 i 11302 n 10102 s 8841 c 7612 u 7602 l 6079 m 5975 d 5571 b 5421 p
入力ファイルは日本語が含まれていても大丈夫です。
wordfreq.rb にオプション「-c」を加えることで、処理をまとめたスクリプトも用意しました。
そちらも参照してください。
途中経過を確認できるということで、短いスクリプトなので、全部入れておきます。
Web ブラウザでの表示上は Ruby のスクリプトですが、HTML の特殊文字をエスケープしています。 テキストとしてセーブしてご利用ください。
wordfreq.rb 単語を数えます。
#! /usr/local/bin/ruby -Ke
# /home/tetsu/src/ruby/sdk/wordfreq.rb
# Created: March 10,2001 Saturday 02:11:26
# Author: tetsu(WATANABE Tetsuya)
# $Id: wordfreq.rb,v 1.2 2001/03/09 17:30:17 tetsu Exp $
# usage:
require 'nkf'
c = Hash.new(0)
while gets
NKF.nkf('-eZm', $_).scan(/\w+/) do |w|
c[w] += 1
end
end
c.keys.sort do |a, b|
[c[b], a] <=> [c[a], b]
end.each do |k|
printf "%4d %s\n", c[k], k
end
charfreq.rb 文字を数えます。
#! /usr/local/bin/ruby -Ke
# /home/tetsu/src/ruby/sdk/charfreq.rb
# Created: March 10,2001 Saturday 02:12:16
# Author: tetsu(WATANABE Tetsuya)
# $Id: charfreq.rb,v 1.2 2001/03/09 17:32:14 tetsu Exp $
# usage:
require 'nkf'
c = Hash.new(0)
while gets
NKF.nkf('-eZm', $_).scan(/\w/) do |w|
c[w] += 1
end
end
c.keys.sort do |a, b|
[c[b], a] <=> [c[a], b]
end.each do |k|
printf "%4d %s\n", c[k], k
end
スクリプトとしては、freq.rb としてオプションとして「語」単位か「文字」単位かを分けたほうがいいですね。
正規表現以外はまったく処理が同じですから。
いや、名前から分かりやすい wordfreq.rb にオプション -c でいいかな。
名前は大切ですし?
ということで、次のようにしてみました。
#! /usr/local/bin/ruby -Ke
# /home/tetsu/src/ruby/sdk/wordfreq.rb
# Created: March 10,2001 Saturday 02:11:26
# Author: tetsu(WATANABE Tetsuya)
# $Id: wordfreq.rb,v 1.3 2001/03/09 18:26:56 tetsu Exp $
# usage:
def usage
STDERR.puts "usage: #$0 [-c] ..."
exit 1
end
opt_char = false
reg_pattern = Regexp.new('\w+')
while /^-/ =~ ARGV[0]
$_ = ARGV.shift
if /^-c/
opt_char = true
else
usage
end
end
require 'nkf'
reg_pattern = Regexp.new('\w') if opt_char
c = Hash.new(0)
while gets
NKF.nkf('-eZm', $_).scan(reg_pattern) do |w|
c[w] += 1
end
end
c.keys.sort do |a, b|
[c[b], a] <=> [c[a], b]
end.each do |k|
printf "%4d %s\n", c[k], k
end
この話題は Unix ユーザならよくご存じの?
$ man tar | col -b | tr -sc 'A-Za-z' '\012' | tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr |head
29 archive
25 the
23 files
23 file
19 f
17 to
16 tar
13 of
12 extract
11 t
という単語の数え上げ(語の頻度) wordfreq です。
Unix ではパイプを使えば一行でできてしまう? 内容ですが、Ruby を使っても簡単ですね。
出力形式については、注目しているポイントによって変更してください。
現在は「出現頻度」順になっています。
プログラミング的な応用も可能で、変数名の間違い探しなどに役立ちます。 コンパイラ系や Ruby のように初期化が必要な場合は、変数名の間違いによるバグは入りにくいのです。 でも Awk や Perl のように宣言や初期化が必要のない場合には変数名を一文字間違ったために、みつけにくいバグが入ったりします。 あ、長大なスクリプトを書いた場合の話ですけど。 ま、Perl はオプションの指定でこの辺はクリアできてしまいますけど。 スクリプト自身の確認には、こういうオプションがサポートされていたりするのでいいのですが、出力結果についてはどうでしょう? 出力も予想もしていないものが含まれている可能性があったりします。 こういう確認に使用可能ですね。
wordfreq.rb では日本語の場合は、「単語」がスペースで区切られていたりしないので、ちょっと扱いが悪いです。
ですが、最近は「分かち書き」をしてくれる便利なツールが利用できます。
これを利用すると、次のようなことも可能です。
目的によってはこれも活用できますよね?$ kakasi -w < README.jp | wordfreq.rb | head 50 を 40 の 20 する 19 に 18 は 15 本 14 で 14 プログラム 12 です 11 Ruby