2012-06-08 115 views
0

我試圖從http日誌文件中檢索主機。 通常情況下,我會做這樣的事情:解析帶引號的字符串

cat proxy.log | awk '{ print $16 }' 

但是,日誌文件的格式是這樣的:

2012-05-21 05:55:01 503 <client_ip> - - - OBSERVED "Entertainment" - 200 TCP_RESCAN_HIT GET text/xml;%20charset=UTF-8 http <server_ip> <server_host> 80/?feed=rss2 - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; MS-RTC LM 8; Microsoft Outlook 14.0.6025; ms-office; MSOffice 14)" <proxy_ip> 13356 479 - 

正如你所看到的,某些領域被引用,並有一個動態的量空格。這意味着16美元並不總是返回主機。 我可以使用shlex.split()來解決這個問題,它會返回一個數組。

但是我使用的一些系統沒有安裝python,我不知道如何使bash腳本(帶有標準gnu工具)以這種方式分割日誌條目,即我可以一直處理16美元。

如果讀者有同樣的問題,有蟒蛇可用的,這裏是我的Python的解決方案:

#!/usr/bin/env python 

import shlex, sys, string 
EOF = "" 
if len(sys.argv) == 2: 
     try: 
       field = int(sys.argv[1]) 
     except ValueError: 
       print "error: <field_no> must be a positive integer" 
       sys.exit(1) 
else: 
     print "usage: %s <field_no>" % sys.argv[0] 
     sys.exit(1) 

def process(line): 
     line = string.strip(line) 
     line = shlex.split(line) 
     return line[int(sys.argv[1])] 

line = sys.stdin.readline() 
while not line == EOF: 
     sys.stdout.write(process(line)+"\n") 
     line = sys.stdin.readline() 
+0

在這個例子中,它是主機名,你還能從行尾標識主機名(它將在什麼位置或標記)? – Raghuram

回答

0

如果GET (something) http <server_ip>位是可靠的,你可以使用GNU sed的是這樣的:

$ cat proxy.log 
2012-05-21 05:55:01 503 <client_ip> - - - OBSERVED "Entertainment" - 200 TCP_RESCAN_HIT GET text/xml;%20charset=UTF-8 http <server_ip> <server_host> 80/?feed=rss2 - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; MS-RTC LM 8; Microsoft Outlook 14.0.6025; ms-office; MSOffice 14)" <proxy_ip> 13356 479 - 
$ cat proxy.log | sed -r 's/^.*(GET|POST) [^ ]+ http ([^ ]+) .*$/\2/' 
<server_ip> 
+0

很好的答案,但這個查詢可能會出現幾個問題。你有http命令TRACE,OPTIONS等等也要考慮。它可能是另一種傳輸比http(https,gopher?!)。唯一保持不變的是字段的數量,封裝在「」中,如果它可以包含空格。 –

0

如果你只想擺脫可變數量的空間,可以在awk之前使用sed

cat proxy.log | sed 's/ */ /g' | awk '{ print $16 }' 

用替換S/*// g的空格的任何正量被剝離到一個

+0

對不起,但這不起作用。 「娛樂」也可以是「娛樂,電腦和互聯網」。我試圖做的是能夠把這個在一些陣列中,即9美元將是「娛樂,電腦和互聯網」 –

+0

我認爲你可以嘗試像「替換所有空格,有奇數的引號之前「,但我想不出用sed做這件事的方法。 perl可以管理 – Hachi

0

我想嘗試以匹配字段,其中前一個字段是一個IP地址和下一個字段是一個整數:

perl -MRegexp::Common -ane ' 
    $n=16; 
    while ($n < @F) { 
    if ($F[$n-2] =~ /$RE{net}{IPv4}/ and $F[$n] =~ /^\d+$/) 
     print "$F[$n-1]\n"; 
     break; 
    } 
    $n++; 
    } 
' filename