- ベストアンサー
ログの集計で
ログの集計で困っております。 そのログというのがジョブの開始時刻と終了時刻が別々の行に出力されているもので、 このログをジョブごとに開始と終了時刻を別々の行から取得し、出力結果は1行に1ジョブで出したいと考えています。 ログがUNIXのログなので、当初はshellスクリプトでと思っていたのですが、 shellだとログを何度も先頭から読み込む形となり、perlで可能ではないかと思い、質問させていただきました。 perlはあまり詳しくはないですが、よろしくお願いいたします。 元のログイメージ ~~~ここから~~~ START 08:00:00 Job001 START 08:05:00 job002 END 08:07:01 job001 START 08:08:00 job003 END 08:10:00 job002 : ~~~ここまで~~~ 出力イメージ ~~~ここから~~~ job001 08:00:00 - 08:07:01 job002 08:05:00 - 08:10:00 : ~~~ここまで~~~
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
キーがホスト名(?)のハッシュ(連想配列)に、STARTやらENDやらのデータを放り込んでいって、 最後まで行ったらそこから必要なデータを取り出せばよいです。 これはちとやりすぎの例 use strict; use warnings; use feature ':5.10'; my %log; while (<DATA>) { chomp; my ($kind, $time, $host) = split q{ }, $_, 3; $log{$host} ||= [$host]; push @{$log{$host}}, $time; } map {printf "%s %s - %s\n", $_->[0], $_->[1], $_->[2]} sort {$a->[1] cmp $b->[1]} grep {@$_ > 2} values %log; __END__ START 08:00:00 job001 START 08:05:00 job002 END 08:07:01 job001 START 08:08:00 job003 END 08:10:00 job002 結果: job001 08:00:00 - 08:07:01 job002 08:05:00 - 08:10:00 一番最初のデータが Job001 か job001 なのかよくわからないのと、 大小文字の違いを無視していいかどうかわからなかったので 適当にやってます。 最初はハッシュに放り込むのを時刻データの文字列にする (STARTとENDの時刻は適当な記号で連結する)のが 理解しやすいんじゃないでしょうか。
その他の回答 (2)
- pick52
- ベストアンサー率35% (166/466)
Perlの連想配列(ハッシュ)は順番を保存する機能がないのでバラバラに なってしまいますが以下のようにしたらどうでしょうか。 (以下は単純に文字列を処理しているので実際にはその文字列処理の 部分をファイル処理に変えてやればいいです) use strict; my $LOG = <<'LOG'; START 08:00:00 Job001 START 08:05:00 job002 END 08:07:01 job001 START 08:08:00 job003 END 08:10:00 job002 LOG my $log = {}; foreach(split(/\n/, $LOG)) { my ($flg, $time, $job) = split(/\s/, $_); $log->{lc($job)}->{uc($flg)} = $time; } while(my ($key, $value) = each(%$log)) { printf("%s %s - %s\n", $key, $value->{'START'}, $value->{'END'}); } 1; 順番を保存したい場合はTie::IxHashというPerlモジュールを使用して ください。
お礼
ご回答ありがとうございます。 参考になりました。 参考URL先も見させて頂きました。 こちらも色々と参考になる例があり、非常に助かりました。 ありがとうございました。
>perlはあまり詳しくはないですが、よろしくお願いいたします。 どのくらい書けますか? 連想配列を使えば簡単に出来そうです。
お礼
返答ありがとうございます。返事が遅くなりました。 単純なテキストから項目を抽出する という程度がなんとか出来るくらいです。 連想配列についても、そういうのがあるという事は知っていましたが、 使ったことがありませんでした。 で 連想配列が今回のに使えそうだということはネットで調べて見たのですが、 具体的に今回のログ集計にどう使うのか?まではまだ分かっていないです。 よろしければ連想配列の使い方などを教えていただければと思います。 よろしくお願いします。
お礼
ご回答ありがとうございます。 なるほど。 一行づつ読んで処理するのではなく、全部読み取ってから、メモリ上で処理させるのですね。 shellだと一行づつ読んで・・と思っていたので、これなら処理時間的にも問題なさうです。 map関数など知らなかったこともあり、勉強になりました。 まだ自分の中で消化し切れてない部分もありますが、何度か試して理解していきます。 本当にありがとうございました。