로그 파일에서 특정 정보 가져오기

로그 파일에서 특정 정보 가져오기

로그 파일에서 일부 부분을 가져오고 싶습니다. 사용자, 모듈, 작업, 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으나 다음을 사용하여 요청을 찾을 수 있는 일곱 번째 열만 잘라내려고 했습니다.

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

설명하다

  1. 펄 옵션:

    -l 만들다ORS = RS = \n

    -a@F현재 레코드를 분할하여 얻은 배열에 필드를 저장합니다 /\s+/. 예를 들어 다음과 같습니다.$F[0] => $1, $F[1] => $2, ..., $F[-1] => $NF

    -n 요청하지 않는 한 출력하지 않고 입력 파일을 한 줄씩 읽는 암시적 루프를 설정합니다.

  2. 시작 블록:

    먼저 제목을 인쇄합니다. 그런 다음 헤더를 기반으로 형식을 동적으로 결정합니다. 읽은 각 줄에 대해 키가 = 앞의 문자열이고 값이 = 뒤의 문자열인 해시 %h를 설정합니다. 표시할 문자열은 왼쪽에 ? 또는 & 바로 옆에, 오른쪽에 & 바로 옆에 있습니다. 다음으로, 키의 이름이 해시의 %h 버전으로 바뀌는 또 다른 해시 %H를 설정합니다. 다음으로 BEGIN 블록에서 계산된 형식에 따라 해시 값을 인쇄합니다.

관련 정보