Sed

從日誌中過濾多行

  • April 18, 2015

這個問題應該轉移到stackoverflow嗎?

我經常需要使用 log4j 讀取 java 應用程序生成的日誌文件。通常,一條記錄的消息(我們稱之為日誌條目)跨越多行。例子:

INFO  10:57:01.123 [Thread-1] [Logger1] This is a multi-line
text, two lines
DEBUG 10:57:01.234 [Thread-1] [Logger2] This entry takes 3 lines
line 2
line 3

請注意,每個日誌條目都從一個新行開始,並且該行的第一個單詞是 TRACE、DEBUG、INFO 或 ERROR 以及至少一個空格。這裡有 2 個日誌條目,第一個在毫秒 123,另一個在毫秒 234。

我想要一個快速命令(使用 sed/grep/awk/etc 的組合)來過濾日誌條目(grep 只過濾行),例如:刪除所有包含文本“Logger2”的日誌條目。

我考慮進行以下轉換:

  1. 使用特殊的字元序列(例如:##)連接屬於相同日誌條目的行;這樣,所有的日誌條目將只佔一行
INFO  10:57:01.123 [Thread-1] [Logger1] This is a multi-line##text, two lines
DEBUG 10:57:01.234 [Thread-1] [Logger2] This entry takes 3 lines##line 2##line 3
  1. grep

  2. 將行拆分回來(即:用\n替換##)

我在第 1 步遇到了麻煩——我沒有足夠的 sed 經驗。

也許上面的 3 個步驟不是必需的,也許 sed 可以完成所有工作。

無需混合多種樂器。sed任務只能由

sed '/^INFO\|^DEBUG\|^TRACE\|^ERROR/{
        /Logger2/{
            :1
            N
            /\nINFO\|\nDEBUG\|\nTRACE\|\nERROR/!s/\n//
            $!t1
            D     }
                                   }' log.entry

多行日誌記錄的 perl 過濾器(記錄開始標記)

使用以下 perl 腳本作為工作原型。

用法script_path regular_expression log_files

例如script_path "line \d" log_file_1 log_file_2

#!/usr/bin/perl
$pattern = qr/(?^s)$ARGV[0]/; shift; # process filtering expression
# (?^s) - treats matched string as single line
my $line = ''; # accumulates current log file record/paragraph
while(<>) {
if( /^(TRACE|DEBUG|INFO|ERROR) /o ) { # start of new record
  &flush; # flush/print previous recors
}
$line.=$_;
}
&flush;
exit;

sub flush {
 local $_ = $line;
 if( length($_) and /$pattern/ ) {
   print;
 }
 $line = '';
}

引用自:https://unix.stackexchange.com/questions/197028