我正在尝试从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中解决这个问题,它返回一个数组。
但是我使用的一些系统没有安装python,我想知道这是如何使bash脚本(带有标准的gnu工具)以这样的方式分割日志条目,即我可以一致地解决16美元。
如果读者有同样的问题并且有python可用,这是我的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 :(得分: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>
答案 1 :(得分:0)
如果您只想摆脱可变数量的空格,可以在awk之前使用sed
cat proxy.log | sed 's/ */ /g' | awk '{ print $16 }'
用替换s / * / / g将任何正数量的空格剥离为一个
答案 2 :(得分: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