完全修飾フィールド/列にはありませんが、ログファイルから特定の文字列を抽出する必要があります。たとえば、
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
これは-a
Perlを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つの方法は次のとおりです。
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%,}
アッ
ターゲットパターンをファイルに保存します。
$ 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
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
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
答え2
GNUソリューションawk
:
gawk -v OFS= -v FPAT=',(srcip|srczone|protocol|dstip|dstzone|dstport|rule_name)=[^,]*' -e 'NF > 0 { $1=$1; print }'
ここではGNU固有の機能を使用しますawk
。変数に正規表現を使用してフィールドを書式FPAT
設定し、正規表現に一致する行のすべての部分がに割り当てられるようにします$1...$n
。$1
$1
$0
$1...$n
答え3
これについて少し遅れましたが、提案を提供します。この種のデータはmap
ハッシュに適しています。
#!/usr/bin/env perl
use strict;
use warnings;
#for debugging - can be removed;
use Data::Dumper;
my @fields = qw ( srcip srczone protocol dstip dstzone dstport rule_name );
#read STDIN or files specified on command line (just like grep/sed/awk)
while ( <> ) {
#split commas
#then read key-value pairs.
my %row = map { m/(.*)=(.*)/ } split /,/;
#for debugging:
print Dumper \%row;
#print fields tab-separated and in order as above.
print join "\t", @row{@fields};
}
oneliner-ifyには、スペルを入力する必要があるフィールドのリストがあるため、少し難しいです。しかし:
perl -lane -F, 'BEGIN { @k = qw ( srcip srczone protocol dstip dstzone dstport rule_name ) } %r = map { m/(.*)=(.*)/ } @F; print join "\t", @r{@k}'
答え4
強く打つ
IFS=, read -r -a fields <<< "$date"
results=()
for keyval in "${fields[@]}"; do
IFS='=' read -r key value <<< "$keyval"
case $key in
srcip|srczone|protocol|dstip|dstzone|dstport|rule_name) results+=("$keyval")
esac
done
(IFS=,; echo "${results[*]}")
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All