ライブログファイルの一部の行のみを表示

ライブログファイルの一部の行のみを表示

tailとgrepを使用して関心のある行をフィルタリングし、定期的にリアルタイムで追跡するログファイルがあります。しかし、これらの行には常に興味のないデータがたくさん含まれていますが、行内で必要な部分だけを見ることができるように解析することは困難です。各行エントリの形式は、主にリストラベルと引用符(時にはスペースを含む)で囲まれたデータです。以下は、(削除された)ログ行の例です。

2017:11:29-11:29:56 filter-1 httpproxy[3194]: id="0001" severity="info" sys="SecureWeb" sub="http" name="http access" action="pass" method="CONNECT" srcip="10.11.12.13" dstip="14.3.1.4" user="" group="" ad_domain="" statuscode="200" cached="0" profile="REF_HttPro1234 (Campus2)" filteraction="REF_HttStu (Allow Policy)" size="6518" request="0x915a3e00" url="https://website.net/" referer="" error="" authtime="0" dnstime="1" cattime="73" avscantime="0" fullreqtime="61576999" device="0" auth="6" ua="" exceptions="" category="9998" reputation="unverified" categoryname="Uncategorized" country="United States" application="krux" app-id="826"
2017:11:29-11:29:56 filter-1 httpproxy[3194]: id="0001" severity="info" sys="SecureWeb" sub="http" name="http access" action="pass" method="GET" srcip="10.13.14.15" dstip="154.6.75.10" user="" group="" ad_domain="" statuscode="200" cached="0" profile="REF_HttPro1235 (Campus1)" filteraction="REF_HttStu (Allow Policy)" size="3161" request="0x6b4d5610" url="http://host.com/mini_banner.png" referer="http://www.web.com/computers.htm" error="" authtime="0" dnstime="0" cattime="64" avscantime="848" fullreqtime="50046" device="0" auth="6" ua="Mozilla/5.0 (X11; CrOS x86_64 9765.85.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.123 Safari/537.36" exceptions="" category="111" reputation="trusted" categoryname="Education/Reference" sandbox="-" content-type="image/png"

1つの注意点は、すべてのラベルがすべての行に表示されるわけではないことです。たとえば、application と app-id は最初の行には表示されますが、2 番目の行には表示されません。

上記の行を入力の例として使用して出力として必要な例は、srcip、Categoryname、およびurlタグのみを順番に表示することです。希望の出力は次のとおりです。

10.11.12.13 Uncategorized https://website.net/
10.13.14.15 Education/Reference http://host.com/mini_banner.png

私は表示されたラベルをすぐに調整できるように調整しやすい解決策を探しています。

ベストアンサー1

お客様のデータは高度に構造化されています。キー="値"したがって、gnu awkを使用してキー名のリストを引数として使用し、その値のみを印刷する小さなシェルスクリプトを作成できます。例えばmyscript:

#!/bin/bash
awk -v lhs="$*" '
BEGIN{  FPAT = "[a-z-]*=\"[^\"]*\""
        nwant = split(lhs,want)
}
{       for(i=1;i<=NF;i++){
            start = match($i,/([a-z-]*)="([^"]*)"/,a)
            key[a[1]] = a[2]
        }
        for(i=1;i<=nwant;i++){printf "%s ",key[want[i]]; key[want[i]] = ""}
        printf "\n"
}'

これmyscript srcip categoryname urlにより、awk変数は最初に配列に分割されるlhs単一の文字列に設定されます。want行は awk によってパターンに一致するフィールドに分割されます。キー="値"組み込みFPAT変数を使用します。

各行の各フィールドに対して2つのキャプチャグループに分割しますmatch()。 1つはキー用で、もう1つは二重引用符内の部分用です。これはawkによって配列に格納され、キー文字列でインデックス付けされた連想配列aに保存されます。key

次に、必要な各キーの値を印刷し、その行にそのキーがない場合は、次の行の値を消去します。明らかに、これはすべてのデータが必要な構造を持っていると仮定し、アルファベット以外の文字を持つ値またはキー内で( ")を処理するように変更する必要があります。


4.0より前のGNU awk(gawk)バージョンには、パターンに一致するフィールドにFPAT行を分割する機能が組み込まれていないため、これを直接実行する必要がありました。

#!/bin/bash
awk -v lhs="$*" '
BEGIN{ nwant = split(lhs,want) }
{       input = $0
        while(match(input,"[a-z-]*=\"[^\"]*\"")>0){
            field = substr(input,RSTART,RLENGTH)
            input = substr(input,RSTART+RLENGTH)
            start = match(field,/([a-z-]*)="([^"]*)"/,a)
            key[a[1]] = a[2]
        }
        for(i=1;i<=nwant;i++){printf "%s ",key[want[i]]; key[want[i]] = ""}
        printf "\n"
}'

明らかに、2つの一致呼び出しを1つにまとめることができますが、これは元の一致との違いを示しています。

おすすめ記事