2017-09-14 208 views
2

背景

我使用sed很多來跟蹤以符合特定模式的行開頭的日誌。我使用這個命令:如何使sed匹配多行的模式

sed -ne '/pattern/ p' infile >outfile 

在代碼中,我簡單地追加記錄與標識線,這樣我可以過濾使用它們以後(我的標識是訂單號和線程號..所以例如該日誌行:

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checkout 

是爲了7123線程41361.所以上面的sed命令(如果我濾波有關訂購7123所有日誌)看起來像:

sed -ne '/ORD7123/ p' infile >outfile 

問題

當日志用於單個順序/線程組合跨越多行,像這樣的問題發生:

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 

使用上述sed的命令,我的輸出將看起來像這樣

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 

建議/分析

我們之前遇到過這個問題(我們控制了日誌的創建),我們處理它的方式是用替換新行或類似的東西。在這種情況下,我沒有在日誌中創造太多的控制,所以我必須處理日誌,是

+0

也許這會有幫助嗎? http://www.grymoire.com/Unix/Sed.html#toc-uh-51 – Jerinaw

回答

1

awk應該能夠處理這種可以工作的方式logstash作品並收集日誌信息多行。看看您的示例,您似乎想要捕獲覆蓋多行的{ ... }之間的文本。因此,你可以使用一些鏈接如下:

awk '/ORD7123/{if (/{$/) p=1; print; next} p; p && /^}/{p=0}' file.log 

如果如示例日誌,你並不總是有{ ... },那麼你可以使用這個命令awk

awk '/ORD7123/ {p=NR} NR==p+1 {p = (/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}/? 0 : NR)} p' file 

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 

awk命令查找對於每個日誌行中的開始日期模式,如果它沒有找到它,則認爲它是前一個日誌消息的繼續。

+0

這就是我想從OP得知的日誌消息是否總是有'{...}'。 – anubhava

1

AWK解決方案:

awk -v p="ORD7123" '$0~p{ print; 
      while(getline nl > 0 && (nl!~/^[0-9]+\/[0-9]{2}/ || nl~p)){ 
       print nl 
      } 
     }' inputfile 

的典型輸出:

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 
0

這可能爲你工作(GNU SED):

sed ':a;/ORD7123/!d;:b;n;/^..\?\/..\?\/.... ..:..:.. /ba;bb' file 

比賽所要求的字符串( ORD7123)否則刪除該行。在匹配中,讀取並打印後續行,直到以日期和時間開頭的行,然後檢查所需的字符串。

0

sed適用於各行簡單替換,全部爲。你不是試圖在一條線上做一個簡單的替換,所以你不應該考慮sed。只需使用AWK:

$ cat tst.awk 
/^[0-9]/ { prt() } 
{ rec = (rec=="" ? "" : rec ORS) $0 } 
END { prt() } 
function prt() { 
    if (rec ~ /ORD7123/) { 
     print rec 
    } 
    rec = "" 
} 

$ awk -f tst.awk file 
9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 

它可以很容易地調整,以去除換行符的記錄中,如果你想進一步的處理只需更改ORSOFS要簡單(或者其他任何你喜歡的字符串)正在編譯的記錄:

$ cat tst.awk 
/^[0-9]/ { prt() } 
{ rec = (rec=="" ? "" : rec OFS) $0 } 
END { prt() } 
function prt() { 
    if (rec ~ /ORD7123/) { 
     print rec 
    } 
    rec = "" 
} 

$ awk -f tst.awk file 
9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { "order": "country is required", "credit_card": "year is not a valid year" }. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution