複数行を単一行に変換

複数行を単一行に変換

複数行のログファイルがあり、これを1行のログに変換したいと思います。

複数行の例:

6/13/2015 12:00:47 AM - {   562} START Web 
6/13/2015 12:00:47 AM - Requested Web connection from 123.125.71.103 [123.125.71.103], ID=562 
6/13/2015 12:01:24 AM - {   563} START POP3 
6/13/2015 12:01:24 AM - Requested POP3 connection from 10.127.251.37 [10.127.251.37], ID=563 
6/13/2015 12:01:24 AM - (   563) USER [email protected] 
6/13/2015 12:01:24 AM - POP3 connection with 10.127.251.37 [10.127.251.37] ended. ID=563 
6/13/2015 12:01:24 AM - {   563} END POP3
6/13/2015 12:01:24 AM - {   564} START POP3 
6/13/2015 12:01:24 AM - Requested POP3 connection from 10.127.251.37 [10.127.251.37], ID=564 
6/13/2015 12:01:24 AM - (   564) USER [email protected] 
6/13/2015 12:01:24 AM - POP3 connection with 10.127.251.37 [10.127.251.37] ended. ID=564 
6/13/2015 12:01:24 AM - {   564} END POP3
6/13/2015 12:01:40 AM - Web connection with 123.125.71.103 [123.125.71.103] ended. ID=562 
6/13/2015 12:01:40 AM - {   562} END Web

まず、同じログID(たとえば「562」)に一致するこのような単一の出力ラインが必要です。

6/13/2015 12:00:47 AM - {   562} START Web 6/13/2015 12:00:47 AM - Requested Web connection from 123.125.71.103 [123.125.71.103], ID=562 6/13/2015 12:01:40 AM - Web connection with 123.125.71.103 [123.125.71.103] ended. ID=562 6/13/2015 12:01:40 AM - {   562} END Web
6/13/2015 12:01:24 AM - {   563} START POP3 6/13/2015 12:01:24 AM - Requested POP3 connection from 10.127.251.37 [10.127.251.37], ID=563 6/13/2015 12:01:24 AM - (   563) USER [email protected]  6/13/2015 12:01:24 AM - POP3 connection with 10.127.251.37 [10.127.251.37] ended. ID=563  6/13/2015 12:01:24 AM - {   563} END POP3
6/13/2015 12:01:24 AM - {   564} START POP3 6/13/2015 12:01:24 AM - Requested POP3 connection from 10.127.251.37 [10.127.251.37], ID=564 6/13/2015 12:01:24 AM - (   564) USER [email protected]  6/13/2015 12:01:24 AM - POP3 connection with 10.127.251.37 [10.127.251.37] ended. ID=564  6/13/2015 12:01:24 AM - {   564} END POP3

次のbashスクリプトを完了しましたが、すべての「POP3」または「Web」メッセージをメッセージIDに基づいて分離するのではなく、1行にマージするため、期待どおりに機能しません。

スクリプト:

#!/bin/bash

HOME=/var/tmp/test.txt

ID=`((awk '$6 ~/[0-9]\W/ {print $6}' $HOME | awk '{gsub (/)/, ""); print}' | awk '{gsub (/}/, ""); print}') && (awk '$11 ~/[0-9]/ {print $11}' $HOME | awk '{gsub ("ID=", ""); print}'))`


for ID in $HOME
do
        awk '!/Web/' $HOME | xargs >> final.txt
        awk '/Web/' $HOME | xargs >> final.txt
done

同じIDのみをマージするループを作成する方法についての提案はありますか?

ベストアンサー1

すべてをawkで行うことができます。読み取りIDは以下に結合されています。

awk  '{
    line = $0;
    # ID is { XXX } or ( XXX )
    if ( /[{(] *[0-9]+[})]/ ) {
        id = $0;
        sub(/ *[})].*/,"", id);
        sub(/.*[({] */,"", id);
    }
    # ID is ID=XXX
    else if ( $NF ~ /ID=/ ) {
        id = $NF;
        sub(/[^=]*=/,"",id);
    }
    # else ID= previous value

    # save line into a assoc. array of IDs
    final[id] = final[id]""line" "; # add space between lines
}
END {
    # print foreach id
    for ( id in final ) {
        print final[id];
    }
}
' /var/tmp/text.txt

印刷IDなどの冗長情報を減らし、次のプレフィックスのみを使用できます。

     # remove ID
     sub(/ID=[0-9]/,"",id);
     sub(/[({] *[0-9]+[})]/,"",id);

     END {
         # print foreach id
         for ( id in final ) {
             #Print ID then the rest of the line
             printf("[ID=%d]: %s\n", id, final[id]);
         }
     }

おすすめ記事