ログファイルから複数のカンマ区切り文字列を抽出する方法は?

ログファイルから複数のカンマ区切り文字列を抽出する方法は?

完全修飾フィールド/列にはありませんが、ログファイルから特定の文字列を抽出する必要があります。たとえば、

date="2017-01-03 08:30:02 -0500",fac=f_kernel_ipfilter,area=a_general_area,type=t_attack,pri=p_major,hostname=hostname,category=policy_violation,event="ACL deny",attackip=1.1.1.1,attackzone=internal,app_risk=low,app_categories=remote-admin,netsessid=c550e586ba75a,src_geo=US,srcip=1.1.1.1,srcport=38256,srczone=internal,protocol=6,dst_geo=US,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All,reason="Traffic denied by policy.",application=SSH

srcip、srczone、プロトコル、dstip、dstzone、dstport、およびrule_nameを取得したいと思います。私は現在、不要なOUTフィールドを削除するためにPerlの怠惰なマッチングを使用しています。,dstport=80,ログファイルの場所に関係なく、この8つの文字列とカンマ内のデータのみを取得する方法はありますか?同じデータの入力位置が異なるため、これを困難にします。

ベストアンサー1

迅速で汚い方法は次のとおりですperl

$ perl -F, -lane '@l = grep {/srcip|srczone|protocol|dstip|dstzone|dstport|rule_name/} @F; 
                  print join ",",@l' file 
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All

これは-aPerlをawkのように振る舞い、与えられた文字に基づいて入力行を分割して配列-Fの要素として保存します@F。その後、grep配列を作成し、配列のターゲット単語に一致する要素を保持し、@l最後に@l印刷接続にコンマを使用します。

パターンのいずれかがサブパターンになる可能性がある場合、これは失敗します(foo=barおよびがあると仮定)。foobar=baz

より長いターゲットパターンリストの場合(実際のスクリプトを作成したくない場合)、それを配列に保存してリンクして|grepの正規表現を作成できます。各パターンの周囲に追加して、\bサブパターンが一致しないようにすることもできます。不要な一時配列も削除すると、次のような結果が得られます。

$ perl -F, -lane '
    BEGIN{
     $pat="\\b" . join "\\b|",qw(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=)
    } print join ",",grep {/$pat/}@F' file 
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All

私たちの常駐の専門家はsed awkまたは[。 ..] ~から注文

申し訳ありません。しかし、これは本当にとんでもないことです。各ツールでこれを行う1つの方法は次のとおりです。

  1. Bourneシェル(再)。これを使用しないでください。私はそれが可能であることを証明するためにお見せするだけです。

    $ pat=(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=); 
    $ o=""; while IFS=, read -a fields; do 
                for f in "${fields[@]}"; do 
                    for pat in "${pat[@]}"; do 
                        [[ $f =~ $pat ]] && o="$f,$o"
                    done 
                done
               done < file ; echo ${o%,}
    
  2. アッ

    ターゲットパターンをファイルに保存します。

    $ cat patterns
    srcip
    srczone
    protocol
    dstip
    dstzone
    dstport
    rule_name
    

    それから:

    $ awk -F, '(NR==FNR){ 
                    pat[$0]++; 
                    next;
                } 
                {
                    for(i=1;i<=NF;i++){ 
                        split($i,a,"="); 
                        if(a[1] in pat){
                            printf "%s=%s,",a[1],a[2]
                        }
                    }
                    print ""
                }' patterns file | sed 's/,$//'
    srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All
    
  3. sed(およびシェル)

    $ pat=(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=);
    $ for p in ${pat[@]}; do 
        sed -E "s/.*($p[^,]*).*/\1/" file; done | 
            sed ':a;N;$!ba;s/\n/,/g'
    srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstzone=external,dstport=80,rule_name=Deny_All
    
  4. Bourneシェル(またはすべてのPOSIXシェル)+ sed(1.しないでください。可能ですがばかです)

    $ set srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=
    $ for f in "$@"; do sed "s/.*\($f[^,]*\).*/\1/" file; done | sed ':a;N;$!ba;s/\n/,/g'
    srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstzone=external,dstport=80,rule_name=Deny_All
    

おすすめ記事