• 締切済み

awkの処理速度を改善したい

10万行近いファイルについて、 awkを使用して処理を行っているのですが、 何しろ時間がかかります。 改善方法があれば教えていただきたく よろしくお願いします。

みんなの回答

回答No.8

#7の補足にあるスクリプトだと、 BEGINより前は awkスクリプトじゃないし、最後にある '>> ALLHOST-REC-"${YEAR}"-"${MONTH}"-"${DAY}"_rsp_JIKEIRETU.csv done も awkスクリプトじゃないです。 ここを切らないで a2pに食わせたらそりゃエラーになるのも当然かと。 BEGINの行から ENDの閉じブレースまでを食わせれば a2p sample.awk >sample.pl Please check my work on the 2 lines I've marked with "#???". The operation I've selected may be wrong for the operand types. 警告は出ますがエラーにはなりません。

taka394
質問者

補足

ありがとうございます。 ご指摘通り実行した結果、BEGINの行から ENDの閉じブレースまでを perlに変換できました。 あとは、perlに変換されたファイルをaaa.plとして、 for FNAME in `ls ????????_requrl_ESV_????????.log` do cat "${FNAME}" | awk -F , -v syokai_flag=${SYOKAI_FLAG} ' perl aaa.pl '>> ALLHOST-REC-"${YEAR}"-"${MONTH}"-"${DAY}"_rsp_JIKEIRETU.csv done とすれば、よろしいのでしょうか。 よろしくご指導願います。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.7

>自動生成を行おうとa2p aaa.sh > aaa.perl を実行したところ、Command Not Found と出力され、変換できませんでした。 >また、aaa.sh中には、awkでない部分も含まれている のですが、a2p aaa.sh > aaa.perlとしてよろしいのでしょうか。 まず、a2pがCommand Not Foundになる件ですが、a2pにパスが通っていない可能性があります。 (当方の環境solaris 10(5.10) INTEL版)では、 /usr/perl5/5.8.4/bin/にa2pが入っていました。 もし、その付近にないようでしたら、 ちからわざになりますが、findコマンドでルート(/)からa2pを検索して下さい。(但し、rootユーザの権限が必要ですが) find / -name a2p とすれば a2pのファイルが検索できます。 みつかれば、そのa2pをフルパスで指定して下さい。 次に、 a2p aaa.sh > aaa.perl としてよいかですが、 これは出来ません。 aaa.sh中のawkの部分を外にだして、aaa.awkという、awk専用の スクリプトを作成して下さい。 そのあとで、 a2p aaa.awk > aaa.pl (通常、perlの拡張子は.plにします) として下さい。 これで、aaa.awkからaaa.plが作成されます。 aaa.plの呼び出しは、perl aaa.pl とすればできます。

taka394
質問者

補足

ありがとうございます。 a2pについては、ご指摘通り実行し、 短いawkスクリプトはperlスクリプトに変換できました。 しかし、自分の作成したプログラムについては、 Syntax Errorが発生し、うまく変換できません。 どのようにすれば良いのか教えて下さい。 下記に、対象のプログラム(文字制限から一部省略)を 記載しました。お手数ですが、よろしくお願い致します。 for FNAME in `ls ????????_requrl_ESV_????????.log` do cat "${FNAME}" | awk -F , -v syokai_flag=${SYOKAI_FLAG} ' BEGIN{ end_f = 0; time_count = int(24 * 60 / interval); if (int(24 * 60 % interval) != 0){ time_count = time_count + 1; } item_count = 0; } { if (end_f == 0){ if (NF == 1){ if (substr($1,1,4) == substr(date,1,4)){ time = substr($1,12,2) * 60; time_pos = int(time / interval) + 1; } else{ end_f = 1; } } else if ($1 != "index"){ find_f = 0; } } } END{ for(item_pos = 1;item_pos <= item_count;item_pos++){ for(time_pos = 1;time_pos <= time_count;time_pos++){ printf(",%s",max[item_pos,time_pos]); if (item_max_max < max[item_pos,time_pos]){ item_max_max = max[item_pos,time_pos]; item_max_max_pos = time_pos; } } printf(",*****,%s",item_max_max); } }'>> ALLHOST-REC-"${YEAR}"-"${MONTH}"-"${DAY}"_rsp_JIKEIRETU.csv done

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.6

a2pはawkスクリプトを変換するものであって、シェルスクリプトを変換するものじゃありません。 perlが入っているのなら、perldoc a2p で詳しいヘルプが読めます。 NAME a2p - Awk to Perl translator SYNOPSIS a2p [*options*] [*filename*] DESCRIPTION *A2p* takes an awk script specified on the command line (or from standard input) and produces a comparable *perl* script on the standard output. {    (省略)   } END{    (省略)   }' 肝心なところが省略されてますがな。 さらせないものならそのまま貼り付けなくてもいいですけど どういう処理をしているかの概略くらいは。 まあ全体の構成からすると連想配列にデータを溜め込んでから 最後にそれを使って何かやるんでしょうね。 であれば Perlに置き換えることで速くなる可能性はありますね。 awk以外でごちゃごちゃやってるのも Perlで書けるでしょう。 もっともそれをやってくれるトランスレータはないでしょうけど。

taka394
質問者

補足

for FNAME in `ls ????????_requrl_ESV_????????.log` do cat "${FNAME}" | awk -F , -v syokai_flag=${SYOKAI_FLAG} ' perl aaa.pl '>> ALLHOST-REC-"${YEAR}"-"${MONTH}"-"${DAY}"_rsp_JIKEIRETU.csv done としたところ、 awk:ファイル"[command line]":行1:構文エラー が発生しました。 (aaa.plはa2pによりperlに変換した部分です。) どのようにすればよろしいのでしょうか。 教えて下さい。よろしくお願いいたします。

  • iriyak
  • ベストアンサー率48% (40/82)
回答No.5

こんにちは。 ANo.1 さんのおっしゃる通り、背景情報の補足が期待されます。 (回答者のコメント) 回答者も一ヶ月間のログの解析作業のために二桁万行のボリュームを相手に Awk を使用した経験があります。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

perlで実行されては、いかがでしょうか。 perlには、a2p (AWK to perl)というコマンドがあり、AWKのスクリプトから perlのスクリプトを自動生成してくれます。 a2pで自動生成されたスクリプトをperlで実行すれば、速くなる可能性があります。 今回のケースが、どのくらい速くなるかは、保証できませんが、以前、AWKで処理していて、遅かったのをperlに変えて、かなり速くなった記憶があります。

taka394
質問者

補足

ありがとうございます。 perlで実行することにしました。 現在、Solaris(SunOS 5.9)上でシェル(aaa.sh)を実行しており、 その内容は、 #!/bin/bash for FNAME in `ls ????????.log` do HOSTNAME=`echo "${FNAME}" | cut -b1-8` cat "${FNAME}" | awk -F , ' BEGIN{ (省略) } {    (省略)   } END{    (省略)   }' > "${HOSTNAME}".rsl done といった感じです。 処理内容としましては、 ログファイル(????????.log)から、 最大や平均を求め、 結果ファイル(????????.rsl)に出力するものです。 ところで、perlは入っているようですが、 自動生成を行おうと a2p aaa.sh > aaa.perl を実行したところ、 Command Not Found と出力され、変換できませんでした。 また、aaa.sh中には、awkでない部分も含まれている のですが、a2p aaa.sh > aaa.perl としてよろしいのでしょうか。 自動生成について、その詳細を教えて下さい。 よろしくお願いします。

  • mahaze
  • ベストアンサー率29% (217/731)
回答No.3

Cでプログラム作ればawkより圧倒的に速いと思います。

回答No.2

少なくとも、どんなスクリプトを書いて何を実行していて遅いのかがわからないと、何も言えないです。 「マシンの性能を、考えられる最高のものにしてください」とかになりますかね。それでもどの程度の効果があるかわかりませんが、例えば 32bit x86のunixサーバから、sun sparc64 VIの128 cpu くらいに変更したら、きっと目に見えて効果があると思いますけど。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

今現在どのようなことをどのようにやっているかの情報もなしに アドバイスできる人はそうそういないんじゃないでしょうか。

関連するQ&A