
ログファイルからいくつかの部分を取得したいのですが、ユーザー、モジュール、アクション、doAjax、ajaxActionを取得するためにリクエスト部分をカットしようとしました。
例えば、私は
195.xx.x.x - - [25/Apr/2017:09:60:xx +0200] "POST /userx/index.php?m=contacts&a=form&...
192.xx.x.x - - [25/Apr/2017:09:45:xx +0200] "POST /usery/index.php?m=customer&doajax=request&action=getContacts...
197.xx.x.x - - [25/Apr/2017:09:20:xx +0200] "GET /userx/index.php?m=meeting&doajax=date&id=3
そして私は以下を持ちたいです:
[user]|[module]|[action]|[doAjax]|[ajaxAction]
usery contacts form null null
userx customer null request getContacts
userz meeting null date null
どこ:
userx --> user
m=xxx -->module
a=xxx -->action
doajax=xxx-->doAjax
action=xxx-->ajaxAction
、setを使用しようとしましたawk
が、次のコマンドでリクエストを見つけることができる 7 番目の列だけを切り取りました。
awk '{printf $7; next ; }' logfile
では、リクエストだけを印刷した後、ユーザー、モジュール、アクション、doAjax、ajaxAction を抽出するにはどうすればよいのでしょうか?
答え1
Perl の「ワンライナー」:
$ perl -lne '
BEGIN{
printf "%-10s%-10s%-10s%-10s%-15s\n", qw([user] [module] [action] [doAjax] [ajaxAction]);
}
$usr = $mde = $act = $doAj = $ajAc = "null";
$usr=$1 if m|\s/([^/]+)/|;
$mde=$1 if /m=(.+?)(&|$)/;
$act=$1 if /a=(.+?)(&|$)/;
$doAj=$1 if /doajax=(.+?)(&|$)/;
$ajAc=$1 if /action=(.+?)(&|$)/;
printf "%-10s%-10s%-10s%-10s%-15s\n", ($usr,$mde,$act,$doAj,$ajAc)' file
[user] [module] [action] [doAjax] [ajaxAction]
userx contacts form null null
usery customer null request getContacts
userx meeting null date null
ここでの基本的なトリックは、URL 部分を識別する各文字列を検索し、見つかった場合は対応する変数を設定することです。いずれの場合も、識別子の後に が続き=
(例m=
)、次に または&
行末 が続く を探します(&|$)
。一致した部分は括弧で囲まれるため (例m=(.+?)
)、それを として参照することができ$2
、それが各変数に保存されます。
本当に区切り文字が必要で|
、出力が読みにくくなることに異論がない場合は、代わりにこれを使用できます。
$ perl -lne '
BEGIN{
printf "%s|%s|%s|%s|%s\n", qw([user] [module] [action] [doAjax] [ajaxAction]);
}
$usr = $mde = $act = $doAj = $ajAc = "null";
$usr=$1 if m|\s/([^/]+)/|;
$mde=$1 if /m=(.+?)(&|$)/;
$act=$1 if /a=(.+?)(&|$)/;
$doAj=$1 if /doajax=(.+?)(&|$)/;
$ajAc=$1 if /action=(.+?)(&|$)/;
print join "|", ($usr,$mde,$act,$doAj,$ajAc)' file
[user]|[module]|[action]|[doAjax]|[ajaxAction]
userx|contacts|form|null|null
usery|customer|null|request|getContacts
userx|meeting|null|date|null
より良い(より読みやすい出力)アプローチは、printf
代わりに以下を使用することです。
答え2
これを awk で実行したい場合は、次のようにします。 Split を使用すると、任意のフィールド区切り文字を使用して文字列を分割できます。
awk '{split($7,a,"/"); split(a[3],b,"m="); split(b[2],c,"&"); split(c[2],d,"="); print a[2], c[1], d[1], d[2] }' logfile
これにより、必要な列が生成されます。
userx contacts a form
usery customer doajax request
userx meeting doajax date
残りのステップはフォーマットです。awkの配列は連想配列であり、文字列でインデックス付けできます。ここ次のようにすることができます。ここで、op (output の略) は null に初期化されます。次に、 を設定しますop[d[1]]=d[2]
。
awk '{split($7,a,"/"); split(a[3],b,"m="); split(b[2],c,"&"); split(c[2],d,"="); op["a"]="null"; op["doajax"]="null"; op["ajaxaction"]="null"; op[d[1]]=d[2];print a[2], c[1], op["a"], op["doajax"], op["ajaxaction"] }' junk.txt
[変更後]
awk '{split($7,a,"/"); split(a[3],b,"m="); split(b[2],c,"&"); split(c[2],d,"="); op["a"]="null"; op["doajax"]="null"; op["action"]="null"; op[d[1]]=d[2]; split(c[3],f,"="); split(f[2],g,"."); op[f[1]]=g[1]; print a[2], c[1], op["a"], op["doajax"], op["action"] }' junk.txt
出力は次のようになります
userx contacts form null null
usery customer null request getContacts
userx meeting null date null
答え3
perl -lane '
BEGIN {
print $H = join "|", map { s/.*/[$&]/r } @H = qw/user module action doAjax ajaxAction/;
pos($H) = 0;
push(@pos, pos($H)-$p), $p=pos($H) while $H =~ /\[/g;
$fmt = join "", map { "\%-${_}s" } @pos[1..$#pos], length($H)-$p;
}
my(%h, %H) = $F[-1] =~ /[?&]\K([^=]+)=([^&]+)/g;
@H{@H} = ($F[-1] =~ m|^/([^/]+)|, @h{qw/m a doajax action/});
print sprintf $fmt, map { $H{$_} // "null" } @H;
' logfile
結果
[user]|[module]|[action]|[doAjax]|[ajaxAction]
userx contacts form null null
usery customer null request getContacts
userx meeting null date null
説明
Perl オプション:
-l
作るORS = RS = \n
-a
@F
現在のレコードを分割して得られた配列にフィールドを格納するので/\s+/
、例えば、$F[0] => $1, $F[1] => $2, ..., $F[-1] => $NF
-n
入力ファイルを行ごとに読み取り、要求されない限り出力を行わない暗黙のループを設定します。BEGINブロック:
まず、ヘッダーを出力します。次に、ヘッダーに基づいて動的にフォーマットを決定します。読み取られる行ごとに、キーが = の前の文字列で値が = の後の文字列であるハッシュ %h を設定します。調べる文字列は、左側に ? または &、右側に & で区切られます。次に、キーが %h ハッシュの名前変更バージョンである別のハッシュ %H を設定します。次に、BEGIN ブロックで計算したフォーマットに基づいてハッシュを出力します。