Sed
從日誌中過濾多行
這個問題應該轉移到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”的日誌條目。
我考慮進行以下轉換:
- 使用特殊的字元序列(例如:##)連接屬於相同日誌條目的行;這樣,所有的日誌條目將只佔一行
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
grep
將行拆分回來(即:用\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 = ''; }