やっぱりawkは遅い

外部コマンドは遅い。できるだけbuilt-inコマンドを使おうって話。

シェルでよくあるんだけど、ある区切りの○番目を取ってきたい、っていう場面で

foo="aaaa,bbbb,cccc"
bar=`echo $foo | awk -F, '{print $2}'`

ってやる時がある。
けど、これ、むちゃくちゃ無駄。一回しか実行されないなら大したボトルネックにはならないが、ループの中で使うと酷い事になりがち。

awkの場合

#!/bin/sh

typeset -i i=0

while (( i < 10 ))
do
        echo "aaaa,bbbb,cccc" | awk -F, '{print $2}' >/dev/null
        i=$(( i + 1 ))
done
$ time ./awkTest.sh

real    0m0.129s
user    0m0.031s
sys     0m0.098s

readの場合

カンマ区切りをどうやって? っていうとIFS変数とreadコマンドを使う。

#!/bin/sh

typeset -i i=0

while (( i < 10 ))
do
        IFS=, read a b c <<EOF
aaaa,bbbb,cccc
EOF
        echo $b >/dev/null
        i=$(( i + 1 ))
done
$ time ./readTest.sh

real    0m0.024s
user    0m0.012s
sys     0m0.012s

たった10回のループでこれだけの差が出る。

ログファイルなど行数の多いファイルを読み込んだりして解析するようなものの場合、外部コマンドがボトルネックになりがちなので気をつけよう。

追記

コメント、トラックバックを受けるとGmailへ通知。さらにGmailからケータイへ転送されるようにしていたら、朝の4時半ごろにツッコミを受けてしまった。ツッコミを受けそうなタイトルだなと思っていながら変更しなかったオイラが悪いが...。しかも相手は弾子飼氏だよ。

オイラは保守・運用の人で開発の人じゃないからプログラマの世界は詳しくないけど、ちょっとしたスクリプトではPerl,Rubyが多いのかな。お勤め2〜3年くらいしかない経験上で話すけど、Perlは保守・運用の世界では嫌われる。何故ならお客さんもいっしょに関わってくる関係で(お客さんが)知らない言語で書いちゃダメなんだそうだ。
因みに、Perlスクリプトは数回見た事があるが、use Sstrictを使ったものを見た事が無い。困ったものだ。orz
そんなこんなでシェルばかり使っていたら数十行書くのにPerlを書くのが億劫になってしまった。というか大分忘れている。リファレンス無しでは書けそうに無い。
プログラマには想像できないかもしれないが、Cygwin VIMでコード色分けして書いている*1と、『なんでそんなカラフルなの...』と嫌な顔をされるくらいだ。CVS等のバージョン管理システムも無い。変更管理をエクセル表でやるくらいならCVS導入しろと思うのだが...。

「理解しやすい」は多分に主観的ではあるが、少なくともi=$)((i + 1 ))(のようなギミックは不要だ。

404 Blog Not Found:sh, awk, perl & ruby - やっぱりforkは遅い

痛いところを突かれてしまった。単純な計算にこんな事をしなければならないシェルは美しく無いのは承知している。それともwhile )(( i < 10 ))( && )(( i = i + 1 ))(とでも書けば良かったかな...。

*1:UNIX上にはviはあるがvimが無い