这是一行示例日志
03 Jun 2017/13:51:32:553 DEBUG connectors.BaseConnector [] [] [] - Request Message is <soapenv:Envelope xmlns:_0="abc" xmlns:_1="abcd" xmlns:soapenv="abcde" xmlns:v1="abcdef"><soapenv:Header><_0:Trace mustUnderstand="false"></_0:Trace><_0:MsgDetl mustUnderstand="false"><_0:MsgUID>20150103135132968917</_0:MsgUID></_0:MsgDetl><_0:ExtendedHeader><CredentialsRqHdr><PartyId>123456789</PartyId><LoginName>Userid</LoginName><PartyAuth><SecTokenKey><SessKey>SessionID</SessKey></SecTokenKey></PartyAuth></CredentialsRqHdr></_0:ExtendedHeader></soapenv:Header><soapenv:Body><v1:actionList><_1:CommonRq><_1:OrgCode>2009</_1:OrgCode></_1:CommonRq><_1:CustId>12345678</_1:CustId><v1:e123><v1:SortOrder>L</v1:SortOrder><v1:SortSeq>D</v1:SortSeq></v1:e123></v1:actionList></soapenv:Body></soapenv:Envelope>
关键字有、、、,MsgUID
位置不固定。我想要的输出如下:LoginName
CustId
03 Jun 2017/13:51:32:553 MsgUID, LoginName, CustId
答案1
使用 GNUsed
你可以这样做:
sed -Ee '
s/^/\n\n/
s/\n\n/&\n/;s/[[:blank:]]+/\n/3;s/(.*)\n\n(.*)\n(.*)\n/\1\3\n\n\2/
s|<_0:MsgUID>|\n|;s|</_0:MsgUID>|\n|;s/(.*)\n\n(.*)\n(.*)\n/\1 \3\n\n\2/
s|<LoginName>|\n|;s|</LoginName>|\n|;s/(.*)\n\n(.*)\n(.*)\n/\1 \3\n\n\2/
s|<_1:CustId>|\n|;s|</_1:CustId>|\n|;s/(.*)\n\n(.*)\n(.*)\n/\1 \3\n\n\2/
s/\n\n.*//
' log.file
解释
- 我们
\n\n
在行首放置一个标记 , 。该行中找到的所有匹配项都会被扔到该标记的左侧。 - 首先,我们隔离日期时间部分,然后将其移动到标记的左侧。
- 在所有后续步骤中,我们同样隔离感兴趣的标签,并将标签值扔到标记的左侧。
- 完成后,我们只需删除标记右侧的所有内容(包括标记),而模式空间中保留的内容就是我们想要的。
- 注意:此方法可扩展以包含您需要的任意数量的标签。
结果
03 Jun 2017/13:51:32:553 20150103135132968917 Userid 12345678
另一种方法是使用 Perl 正则表达式:
perl -lne '$,=$";
print /^(?:\S+\s+){2}\S+|<(?:_0:MsgUID|LoginName|_1:CustId)>\K(?:.*?)(?=<)/g' log.file
这里我们将OFS
$,
设为。 perl 正则表达式将输出列表中的所有非环视匹配,然后由于 OFS 值已就位,因此将打印空间分隔开。$"
space
/..../g
答案2
我会用sed
它:
sed 's/\(.*:[0-9]* \).*<_0:MsgUID>\([^<]*\).*/\1, \2/'
用于时间戳和 MsgUID。您还可以轻松扩展它以包含 LoginName 和 CustId:形成正则表达式以匹配这些部分并将您想要保留的部分括起来\(\)
。在替换字符串中,您可以将这些部分重用为\1' for the first,
\2 for the second and so on. Try to solve it by understanding the expession for
MsgUID`。如果您没有成功,请将您的代码发布在问题中。