Bash 对日志文件进行复杂的解析,以从多行检索信息并以给定格式存储在新文件中
我有一个文件,不断地填充着如下示例中的条目。Bash 对日志文件进行复杂的解析,以从多行检索信息并以给定格式存储在新文件中,bash,perl,awk,sed,grep,Bash,Perl,Awk,Sed,Grep,我有一个文件,不断地填充着如下示例中的条目。 我想要实现的是匹配一个字符串,存储该行中的一些信息,从上面的某行获取更多细节,并以给定格式将其全部添加到一个新文件中 逻辑可以这样解释: $ cat file a b c d e f g h i j k l m n o p q r s t u v w x y z A B 点击“发送至ABCD的邮件” 以dd.mm.yyyy hh:mi:ss格式存储日期和时间、ID(所有第64个字符,向前15个数字)和消息文本(所有第87个字
我想要实现的是匹配一个字符串,存储该行中的一些信息,从上面的某行获取更多细节,并以给定格式将其全部添加到一个新文件中 逻辑可以这样解释:
$ cat file
a b c d
e f g h
i j k l
m n o p
q r s t
u v w x
y z A B
- 上面的详细信息匹配字符串“Dispatched message to ABCD”并非始终为上面给定的行数,但必须在上面10行以内。 这是由于“Inputfile”正在快速填充,因此为多个同时用户(ID)存储了不同的条目
- 上面10行内具有相同ID的要收集的行必须包含“要处理的事件”
- 时间戳的长度始终相同
- 身份证号码总是15个
- 数字总是10个数字
- visitedCID始终是2或3个数字
- visitedNIC始终是2或3个数字
- vlr可以在5到15个数字之间
- 味精最多可以是250个字符
Inputfile示例:
Thu Jul 24|11:54:58.414|I|DataDispatcher0|Got Event : [ID=240012345678901, eventId = 240012345678901115458, num=4741234567, inbound=false, homeCID=240, homeNID=01, visitedCID=522, visitedNID=01, timestamp=Thu Jul 24 11:54:58 CEST 2014,hno=null,vlr=6012345678, msc=6012345678 eventtype=I, currentCID=null, currentNID=null teleSvcInfo=null camelPhases=null serviceKey=null gprsenabled= false APNlist: null SGSN: null]|com.uws.wmsg2.DataDispatcher|processBlock|393
Thu Jul 24|11:55:06.035|I|DataDispatcher0|Got Event : [ID=240012345678901, eventId = 24001234567890111556, num=null, inbound=false, homeCID=242, homeNID=05, visitedCID=525, visitedNID=05, timestamp=Thu Jul 24 11:55:06 CEST 2014,hno=null,vlr=6012345678, msc=null eventtype=D, currentCID=null, currentNID=null teleSvcInfo=null camelPhases=null serviceKey=null gprsenabled= false APNlist: null SGSN: null]|com.uws.wmsg2.DataDispatcher|processBlock|393
Thu Jul 24|11:55:06.035|W|39|Locking [240012345678901]. No of entries [0]|com.uws.wmsg2.Lock|LockID|58
Thu Jul 24|11:55:06.036|I|24|Event to process : [ID=240012345678901, eventId = 240012345678901115458, num=4741234567, inbound=false, homeCID=242, homeNID=05, visitedCID=525, visitedNID=05, timestamp=Thu Jul 24 11:54:58 CEST 2014,hno=null,vlr=6012345678, msc=6012345678 eventtype=I, currentCID=null, currentNID=null teleSvcInfo=null camelPhases=null serviceKey=null gprsenabled= false APNlist: null SGSN: null]|com.uws.wmsg2.EventProcessor|processEvent|139
Thu Jul 24|11:55:06.041|I|35| Event for dispatching messages 240012345678901115458|com.uws.wmsg2.MSGMessageDispatcher|dispatchMessage|55
Thu Jul 24|11:55:06.072|I|35|Dispatched message to ABCD : ID : 240012345678901, MSG : Welcome to oblivion. There will be no quarrel held. Please enjoy your stay. : ABCD3750251406.195706.62820|com.uws.wmsg2.MSGMessageDispatcher|dispatchMessage|108
Thu Jul 24|11:55:06.074|W|35|Unlocking [240012345678901]. No of entries [1]|com.uws.wmsg2.Lock|UnLockID|64
所需输出:
24.07.2014 11:55:06;240012345678901;4741234567;525;05;6012345678;Welcome to oblivion. There will be no quarrel held. Please enjoy your stay.
我希望我能解释得足够清楚。有人能想出一个方法来实现这一点吗
谢谢 试试这个脚本
#!/bin/bash
logfile=$1
newfile="dispatchclean.csv"
previous=1
current=0
if [[ -n $logfile ]]
then
while read line; do
((current++))
#get a line of interest
LastLineofInterest=`echo $line | grep "Dispatched message to ABCD"`
#if found than get other info
if [[ -n $LastLineofInterest ]]
then
#get the date and convert the format to dd.mm.yyyy
date=`echo $LastLineofInterest | awk -F'|' '{print $1}'`
datedmY=`date -d"$date" +%d.%m.%Y`
#get the time portion hh:mm:ss
time=`echo $LastLineofInterest | awk -F'|' '{$0=substr($2,1,8)}1'`
#get the string between ID and MSG
ID=`echo $LastLineofInterest | sed -E 's/(.*ID : )(.*)(, MSG.*)/\2/'`
#get the string between MSG and :
MSG=`echo $LastLineofInterest | sed -E 's/(.*MSG : )(.*)( :.*)/\2/'`
#look for the ID in the 10 lines before the actual message
#IDinLast10l=`grep -B 10 "Dispatched message to ABCD" $logfile | grep $ID`
IDinLast10l=`sed -n "${previous},${current}p" $logfile | grep $ID`
#get relevant info from above string
num=`echo $IDinLast10l | sed -E 's/(.*num=)(.*)(, inbound.*)/\2/'`
CID=`echo $IDinLast10l | sed -E 's/(.*visitedCID=)(.*)(, visitedNID.*)/\2/'`
NID=`echo $IDinLast10l | sed -E 's/(.*visitedNID=)(.*)(, timestamp.*)/\2/'`
vlr=`echo $IDinLast10l | sed -E 's/(.*vlr=)(.*)(, msc.*)/\2/'`
#append to the newfile
echo "$datedmY $time;$ID;$num;$CID;$NID;$vlr;$MSG" >> $newfile
previous=$current
fi
done < $logfile
else
echo "please supply the logfile as parameter"
fi
#/bin/bash
日志文件=$1
newfile=“dispatchclean.csv”
上一个=1
电流=0
如果[-n$logfile]]
然后
读行时;做
((当前++))
#获取兴趣线
LastLineofInterest=`echo$line|grep“已将消息发送到ABCD”`
#如果找到,请获取其他信息
如果[-n$LastLineofInterest]]
然后
#获取日期并将格式转换为dd.mm.yyyy
日期=`echo$LastLineofInterest | awk-F'|'''{print$1}'`
datedmY=`date-d“$date”+%d.%m.%Y`
#获取时间部分hh:mm:ss
时间=`echo$LastLineofInterest | awk-F'|'''{$0=substr($2,1,8)}1'`
#获取ID和MSG之间的字符串
ID=`echo$LastLineofInterest | sed-E's/(.*ID:)(.*)(,MSG.*)/\2/'`
#获取MSG和之间的字符串:
MSG=`echo$LastLineofInterest | sed-E's/(.*MSG:)(.*)(:.*)/\2/'`
#在实际消息之前的10行中查找ID
#IDinast10L=`grep-b10“已将消息发送到ABCD”$logfile | grep$ID`
IDinast10L=`sed-n“${previous},${current}p“$logfile| grep$ID`
#从上面的字符串中获取相关信息
num=`echo$idinast10l | sed-E's/(.*num=)(.*)(,inbound.*)/\2/'`
CID=`echo$idilast10l | sed-E's/(.*visitedCID=)(.*)(,visitedNID.*)/\2/'`
NID=`echo$idinast10l | sed-E's/(.*visitedNID=)(.*)(,timestamp.*)/\2/'`
vlr=`echo$idilast10l | sed-E's/(*vlr=)(*msc.*)/\2/'`
#附加到新文件
echo“$datedmY$time;$ID;$num;$CID;$NID;$vlr;$MSG”>$newfile
上一个=$当前
fi
完成<$logfile
其他的
echo“请提供日志文件作为参数”
fi
让我们稍微简化您的输入,以隔离问题。给定如下输入文件:
$ cat file
a b c d
e f g h
i j k l
m n o p
q r s t
u v w x
y z A B
下面是如何保持读取最后5行的缓冲区,当看到字母“r”时,从前面第3行打印第2个字段:
$ awk '/r/{split(buf[(NR-3)%5],arr); print arr[2]} {buf[NR%5]=$0}' file
f
在您的情况下,您只需将5
更改为10
,将3
更改为您想要的任何前一行,并使用您喜欢的任何索引访问arr[]
现在-您还需要做什么?您是否可以添加您自己尝试回答此问题的内容,以便我们帮助排除故障?我必须承认,我缺少答案。我甚至不知道该如何处理。也许我可以通过识别“发送至ABCD的邮件”行和合理的格式来处理问题,但我不知道如何识别“匹配上方10行”存在的行,然后将这两行的信息放在一起。抱歉。处理“识别匹配上方10行内存在的行”之类的问题的唯一方法是保留一个缓冲区,其中包含您已处理的行(或您感兴趣的已处理数据),以便您可以搜索该缓冲区。您也必须确保缓冲区不会太大。如果我是您,我会将任务分解为单个问题,然后询问与特定问题相关的问题,显示您尝试过的一些代码。实际上,你基本上是在要求别人为你编写代码,这对任何人都没有好处。谢谢!我确实在sed sub的ID、MSG等方面遇到了一些问题,所以我最终解决了它,例如:MSG=
echo$LastLineofInterest | grep-o-P'(?不客气。它与“GNU-sed版本4.2.1”和“GNU-sed版本4.2.2”一起工作),但您的grep替代方案也可以使用。我发现了另一个缺陷。IDinast10L get中填充了来自距离10行远得多的行的数据,基本上似乎从整个文件中找到了任何匹配项。即使“发送到ABCD的消息”上面的ID没有匹配项但只有在之后。知道为什么吗?它仍然静态地引用dispatch.log而不是变量$logfile。除此之外,我不明白为什么;您有重复的ID吗?是的,我以前将其更改为$logfile。有重复的ID,但不符合-B 10标准。