我使用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
我们之前遇到过这个问题(我们控制了日志的创建),我们处理它的方式是用/n
或类似的方式替换新行。在这种情况下,我无法控制日志创建,因此我必须按原样处理日志
答案 0 :(得分: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
命令在每个日志行中查找起始日期模式,如果找不到,则认为是以前日志消息的延续。
答案 1 :(得分: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
答案 2 :(得分:0)
这可能适合你(GNU sed):
sed ':a;/ORD7123/!d;:b;n;/^..\?\/..\?\/.... ..:..:.. /ba;bb' file
匹配所需的字符串(ORD7123
),否则删除该行。在匹配时,读取并打印后续行,直到以日期和时间开头的行,然后检查所需的字符串。
答案 3 :(得分: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
如果您希望通过将ORS
更改为OFS
(或您喜欢的任何其他字符串)来进一步处理,可以非常轻松地调整以删除记录中间的换行符)正在编制记录的地方:
$ 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