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
  • 点击“发送至ABCD的邮件”
  • 以dd.mm.yyyy hh:mi:ss格式存储日期和时间、ID(所有第64个字符,向前15个数字)和消息文本(所有第87个字符)
  • 检查以上10行中是否有具有相同ID的“要处理的事件”行,并存储visitedCID、visitedNID、vlr
  • 把它缝在一起作为时间戳;身份证件号码;CID;NID;VLR;味精
  • 有一些有用的规则:

    • 上面的详细信息匹配字符串“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标准。