ログファイルからいくつかの部分をインポートしたいと思います。ユーザー、モジュール、アクション、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でこれを行うには、次のようにします。分割では、フィールド区切り文字を使用して文字列を分割できます。
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(出力の略)は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
説明する
パールオプション:
-l
作るORS = RS = \n
-a
@F
現在のレコードを分割して取得した配列にフィールドを保存します/\s+/
。たとえば、次のようになります。$F[0] => $1, $F[1] => $2, ..., $F[-1] => $NF
-n
要求しない限り、出力せずに入力ファイルを1行ずつ読み込む暗黙のループを設定します。スタートブロック:
まずタイトルを印刷します。次に、ヘッダーに基づいてフォーマットを動的に決定します。読み取った各行に対して、キーが=の前の文字列で、値が=の後の文字列であるハッシュ%hを設定します。表示する文字列は左に?または&のすぐ隣に、右側に&右側にあります。次に、キーの名前がハッシュの%hバージョンに変わる別のハッシュ%Hを設定します。次に、BEGINブロックで計算された形式に従ってハッシュ値を印刷します。