tr -s ' ' '\n'
前回は以下のようなコマンドでcalコマンドの結果を行方向に変換した。$ cal | tr -s ' ' '\n' | awk 'NR==2 { mm = $1 } NR==3 { yy = $1 } NR>10 { print mm,$1,yy }'
これはawkの中で行毎にカラム数分ループさせるのがかっこ悪いなあと思ったので、事前に tr でデータの並びを行方向に展開する方法を取っていた。
でも、これって本当に効率がいいんだろうか。
ひょっとして、awkの中でループした方が速いんじゃないだろうか。
カラム方向にループ
同じことをawkの中でループするようにすると。$ time LC_TIME=POSIX cal | tr -s ' ' '\n' | awk 'NR==2 { mm=$1 } NR==3 { yy=$1 } NR>10 { print mm,$1,yy }' | date -f- '+%Y/%m/%d(%a)' | grep -e '[土日]' 2017/06/03(土) 2017/06/04(日) 2017/06/10(土) 2017/06/11(日) 2017/06/17(土) 2017/06/18(日) 2017/06/24(土) 2017/06/25(日) real 0m0.003s user 0m0.006s sys 0m0.002s $ time LC_TIME=POSIX cal | awk 'NR==1 { mm=$1; yy=$2 } NR>2 { for (i=1; i<=NF; i++) print mm,$i,yy }' | date -f- '+%Y/%m/%d(%a)' | grep -e '[土日]' 2017/06/03(土) 2017/06/04(日) 2017/06/10(土) 2017/06/11(日) 2017/06/17(土) 2017/06/18(日) 2017/06/24(土) 2017/06/25(日) real 0m0.002s user 0m0.004s sys 0m0.002s
うーん、全然変わらない。というか、誤差範囲か。この程度では。
データ量が多いと...
もうちょっと、データ量が多い場合をやってみよう。500列 * 10000行のデータで毎行平均値を算出するようにしてみよう。
まずはデータを作る。
$ seq 5000000 | awk "BEGIN { srand($RANDOM); } { print rand() }" | xargs -n500 >rand.dat
これを元に毎行の平均値を算出すると。
$ awk --version GNU Awk 4.1.3, API: 1.1 Copyright (C) 1989, 1991-2015 Free Software Foundation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
$ time cat rand.dat | tr -s ' ' '\n' | awk 'NR%500==1{ s=0 } { s+=$1 } NR%500==0 { print s/500 }' >/dev/null real 0m3.079s user 0m3.393s sys 0m0.076s $ time cat rand.dat | awk '{ s=0; for ( i=1; i<=NF; i++) s+=$i; print s/NF }' >/dev/null real 0m1.875s user 0m1.855s sys 0m0.106s
awkの中でカラム方向にループするほうが速い結果になりました。
毎行、剰余を計算して条件分岐しているので、そりゃそうだという気もしますが...
mawkを使ってみよう
[awk]gawkとmawkで紹介したmawkで、awk内ループバージョンを実行すると。$ mawk -W version internal regex compiled limits: max NF 32767 sprintf buffer 2040
$ time cat rand.dat | mawk '{ s=0; for ( i=1; i<=NF; i++) s+=$i; print s/NF }' >/dev/null real 0m1.204s user 0m1.188s sys 0m0.062s
mawkのほうが3分の2程度の実行時間で完了した。
やっぱり、数値計算が多い場合はmawkを使ったほうが速いのかな。
0 件のコメント:
コメントを投稿