
ログファイルで両方のパターンを一致させ(両方のパターンで)、一致するパターンの次の行を取得し、最後にこれら3つの値を1行に印刷する必要があります。
サンプルログファイル:
2013/09/05 04:26:00 Processing Batch /fbc/dev/cebi/dod/9739867262
2013/09/05 04:26:02 Batch 9739867262 was successful
2013/09/05 04:26:02 Total Time = 3.13 Secs
2013/09/05 04:26:02 Repository API Time = 2.96 Secs
2013/09/05 04:26:02 File System Io Time = 0.06 Secs
2013/09/05 04:26:02 Doc Validation Time = 0.03 Secs
2013/09/05 04:26:02 Ending @ Thu Sep 05 04:26:02 EDT 2013
2013/09/05 08:18:10 Starting @ Thu Sep 05 08:18:10 EDT 2013
2013/09/05 08:18:10 Starting @ Thu Sep 05 08:18:10 EDT 2013
2013/09/05 08:18:10 Processing Batch /fbc/dev/cebi/dod/9844867675
2013/09/05 08:18:10 Processing Batch /fbc/dev/cebi/dod/9886743777
2013/09/05 08:18:16 Batch 9844867675 was successful
2013/09/05 08:18:16 Total Time = 6.00 Secs
2013/09/05 08:18:16 Repository API Time = 5.63 Secs
2013/09/05 08:18:16 File System Io Time = 0.05 Secs
2013/09/05 08:18:16 Doc Validation Time = 0.19 Secs
2013/09/05 08:18:16 Ending @ Thu Sep 05 08:18:16 EDT 2013
2013/09/05 08:18:18 Batch 9886743777 was successful
2013/09/05 08:18:18 Total Time = 8.27 Secs
2013/09/05 08:18:18 Repository API Time = 8.52 Secs
2013/09/05 08:18:18 File System Io Time = 0.08 Secs
2013/09/05 08:18:18 Doc Validation Time = 0.47 Secs
2013/09/05 08:18:18 Ending @ Thu Sep 05 08:18:18 EDT 2013
cust_no.txtというファイルに数字を別々に入れました。
9739867262
9844867675
9886743777
この数値を入力として使用して、ログファイル内の次の2つのパターンを一致させる必要があります。
- プロセスの配置 /fbc/dev/cebi/dod/
- 一括成功
出力には以下が必要です。
->最初のパターン()一致でi.e Processing Batch /fbc/dev/cebi/dod/<numbers in the cust_no.txt>
2番目の単語$ 2を取得する必要があります。 -> 2番目のパターン()一致で2番目の単語、i.e Batch <numbers in the cust_no.txt> was successful
$ 2を取得する必要があります。 -> 2番目のパターンの後、一致の後、次の行の6番目の単語($ 6)(つまり、で始まる行Total Time
)を取得する必要があります。
希望の出力:
9739867262,04:26:00,04:26:02,3.13 Secs
9844867675,08:18:10,08:18:16,6.00 Secs
9886743777,08:18:10,08:18:18,8.27 Secs
これを得るために次のことを試しましたが、うまくいかないようです。
awk -v cn=$cust_no '{{if ($0 ~ "Processing.*" cn) st=$2 && if ($0 ~ "Customer cn was successful" et=$2; getline; tt=$4} ; print st,et,tt}
答え1
これはどうですか:
while read number;do
start=$(grep "Processing Batch /fbc/dev/cebi/dod/$number" log_file\
|head -n 1|awk '{print $2}')
end=$(grep -A 1 "Batch $number was successful" log_file\
|head -n 2|tail -n 1|awk -v OFS=',' '{print $2,$6}')
echo "$number,$start,$end Secs"
done <cust_no.txt
答え2
Perlとgrepを使っても大丈夫なら、ここに問題に対する解決策があります。以下はスクリプトですcmd.pl
。
#!/usr/bin/env perl
use feature 'say';
#use Data::Dumper;
@file = `grep -f cust_no.txt -A 1 sample.log`;
my (%info, $secLineSeen, $time, $custno);
$secLineSeen = 0;
foreach my $line (@file) {
if ($secLineSeen == 1) {
#2013/09/05 08:18:18 Total Time = 8.27 Secs
(my $totTime) = ($line =~ m!\S+ \S+\s+Total Time\s+=\s+(\S+ Secs)!);
$info{$custno}{totTime} = $totTime;
$secLineSeen = 0;
} elsif ($line =~ m/Processing Batch/) {
#2013/09/05 08:18:10 Processing Batch /fbc/dev/cebi/dod/9844867675
($time, $custno) = ($line =~ m!\S+ (\S+)\s+Processing Batch.*/(\S+)!);
$info{$custno}{onetwo} = $time;
} elsif ($line =~ m/Batch.*successful/) {
#2013/09/05 08:18:18 Batch 9886743777 was successful
($time, $custno) = ($line =~ m!\S+ (\S+)\s+Batch (\S+) was.*!);
$info{$custno}{twotwo} = $time;
$secLineSeen = 1;
}
}
#print Dumper(\%info);
#9739867262,04:26:00,04:26:02,3.13 Secs
foreach my $key (sort keys %info) {
say "$key,$info{$key}{onetwo},$info{$key}{twotwo},$info{$key}{totTime}";
}
はい
$ ./cmd.pl
9739867262,04:26:00,04:26:02,3.13 Secs
9844867675,08:18:10,08:18:16,6.00 Secs
9886743777,08:18:10,08:18:18,8.27 Secs
詳細
@file
このPerlスクリプトは、まずこのコマンドの結果を含む配列を作成します。
$ grep -f cust_no.txt -A 1 sample.log
このコマンドは、以下のようにログファイルをインポートし、sample.log
ファイルから顧客番号を含むすべての行を選択します。cust_no.txt
2013/09/05 04:26:00 Processing Batch /fbc/dev/cebi/dod/9739867262
2013/09/05 04:26:02 Batch 9739867262 was successful
2013/09/05 04:26:02 Total Time = 3.13 Secs
--
2013/09/05 08:18:10 Processing Batch /fbc/dev/cebi/dod/9844867675
2013/09/05 08:18:10 Processing Batch /fbc/dev/cebi/dod/9886743777
2013/09/05 08:18:16 Batch 9844867675 was successful
2013/09/05 08:18:16 Total Time = 6.00 Secs
--
2013/09/05 08:18:18 Batch 9886743777 was successful
2013/09/05 08:18:18 Total Time = 8.27 Secs
このgrep
コマンドは、言及する価値がある1つの特別なタスクを実行します。主-A 1
に一致()の後に追加の行を保持します。これにより、「合計時間」を含む行を取得できます。
このデータが抽出されると、Perlスクリプトは質問に記載されている要件に従って多次元ハッシュを使用して、この出力の主要なデータフラグメントの結果を保存します。
コンテンツ処理が完了すると、ハッシュは次のようになります@file
。
$VAR1 = {
'9739867262' => {
'twotwo' => '04:26:02',
'totTime' => '3.13 Secs',
'onetwo' => '04:26:00'
},
'9886743777' => {
'twotwo' => '08:18:18',
'totTime' => '8.27 Secs',
'onetwo' => '08:18:10'
},
'9844867675' => {
'twotwo' => '08:18:16',
'totTime' => '6.00 Secs',
'onetwo' => '08:18:10'
}
};
最後に、このハッシュを繰り返し、質問で指定された形式で収集した内容を印刷します。
答え3
私はgrepを試してみます:
grep -EA 1 'pattern1|pattern2' file.log
-Eオプションを使用して正規表現を拡張し、-Aオプションを使用して一致させる行数を指定します。これで、これを1行で印刷するためにsedを使用する非常にハッキング的な方法を考えることができます。
grep -EA 1 'pattern1|pattern2' file.log | grep -v ^-- | sed 'N ; s+\n+|+g'
sedにコマンドN
(次の行を読む)を渡すと、一度に2行の入力を処理できます。一方、このコマンドを使用すると、s+\n+|+g
処理中の2行間の改行文字を置き換えたり(選択した区切り文字で)削除(置換が空の場合)して、2行目の末尾に新しい行のみを残すことができます。 。
grep -v ^--
最初のgrepインスタンスの出力を削除する必要がありました--
(以下の例を参照)。
Line 1
Line 2
--
Line X
Line Y