検索インデックスを作ろう 前編 〜シェルスクリプトの力〜

1行のシェルスクリプトで単語リストを作る

TAOUP:7.2 Pipes, Redirection, and Filtersを参考にした。

tr -c '[:alnum:]' '[\n*]' | grep -v '^[0-9]*$' | sort -iu
  1. 1番めのコマンドで、アルファベット数字以外を改行に変換する。
  2. 2番めのコマンドで、数字だけの行を消す。
  3. 3番めのコマンドで、行をソートする、ついでに重複を省く。
  4. これで単語リストができる。

文書群はRFCを用いる。英文テキスト243MB。ftp://ftp.rfc-editor.org/in-notes/tar/RFC-all.tar.gz

  • rfc1.txtの単語リストを作ってみる。(
<rfc1.txt tr -c '[:alnum:]' '[\n*]' | grep -v '^[0-9]*$' | sort -iu

A
ARPA
Additionally
After
Again
...
would
write
written
x
yet

  • さらに、単語の出現回数をつけてみる。
<rfc1.txt tr -c '[:alnum:]' '[\n*]' | grep -v '^[0-9]*$' | sort -i | uniq -c

8 A
1 ARPA
1 Additionally
4 After
1 Again
...
10 would
2 write
1 written
1 x
1 yet

各文書を処理する。rfc1.txtのインデックスのファイル名はrfc1.txt.idx。

for file in *.txt; do 
  <$file tr -c '[:alnum:]' '[\n*]' | grep -v '^[0-9]*$' | sort -i | uniq -c >$file.idx
done

インデックスが完成した。さっそくキーワードcoffeeで検索してみよう。grepではなくfgrepを使うと速い。fgrepの結果を、単語の出現回数でソートする。

fgrep coffee *.idx | sort -nk2

rfc1259.txt.idx: 1 coffee
rfc1727.txt.idx: 1 coffee
rfc2905.txt.idx: 1 coffee
rfc4555.txt.idx: 1 coffee
rfc549.txt.idx: 1 coffee
rfc82.txt.idx: 1 coffee
rfc909.txt.idx: 1 coffee
rfc1391.txt.idx: 2 coffee
rfc1539.txt.idx: 2 coffee
rfc1718.txt.idx: 2 coffee
rfc2399.txt.idx: 2 coffee
rfc4485.txt.idx: 2 coffee
rfc546.txt.idx: 2 coffee
rfc2324.txt.idx: 3 coffeepot
rfc3160.txt.idx: 3 coffee
rfc4589.txt.idx: 3 coffee
rfc4677.txt.idx: 4 coffee
rfc2325.txt.idx: 14 coffee
rfc2324.txt.idx: 62 coffee

rfc2324はHyper Text Coffee Pot Control Protocol (HTCPCP/1.0)
だから、うまく動いている。

インデックス作成には、Thinkpad X60で5分かかった。

time fgrep coffee *.idx
real	0m0.335s
user	0m0.264s
sys	0m0.072s
インデックスを使っての検索は0.3秒。
time fgrep coffee *.txt
real	0m0.607s
user	0m0.456s
sys	0m0.152s
直接にファイルを検索は0.6秒。