我正在处理一组数据,我需要将特定字段作为输出:
数据如下所示:
/home/oracle/db.log.gz:2013-1-19T00:00:25 <user.info> 1 2013-1-19T00:00:53.911 host_name RT_FLOW [junos@26.1.1.1.2.4 source-address="10.1.2.0" source-port="616" destination-address="100.1.1.2" destination-port="23" service-name="junos-telnet" nat-source-address="20x.2x.1.2" nat-source-port="3546" nat-destination-address="9x.12x.3.0"]
从上面我需要三件事:
(I) - 2013-1-19T00:00:53.911 which is $4
(II)- source-address="10.1.2.0" which is $8 of which I need only 10.1.2.0
(III) - destination-address="100.1.1.2" which $10 of which I need only 100.1.1.2
我不能使用像-> awk '{ print $4 \t $8 \t $10 }'
这样的简单awk,因为日志文件中的“device_name”之后有一些字段并不总是出现在所有日志行中,所以我必须使用分隔符,例如
awk -F 'source-address=' '{print $2}' | awk '{print $1}
- &gt;这给出了source-addressIP,这是(II)要求
我不知道如何使用awk搜索I和II和III进行组合。
有人可以帮忙吗?
答案 0 :(得分:1)
我相信sed
更适合这项工作
sed -r 's/([^ ]+[ ]+){3}([^ ]+).*[ ]+source-address="([^"]+)".*[ ]+destination-address="([^"]+)".*/\2\t\3\t\4/' file
输出:
2013-1-19T00:00:53.911 10.1.2.0 100.1.1.2
答案 1 :(得分:1)
你到底想要什么?
对于第一种情况,您可以使用您选择的脚本语言解析该行(我的是Perl),或者使用sed
和单个大替换来解决这个问题。或两者之间的东西 - 使用三个正则表达式来获得你想要的部分。
对于第二种情况,您可以调整任何以前的解决方案,最好是sed
解决方案。 awk和sed解决方案已经发布。
对于第三种情况,您可以运行问题中提到的明显awk
解决方案,并将结果发送到{ awk …; awk …; awk …; } < file | consumer
这样的单个管道。
答案 2 :(得分:0)
尝试这样做:
awk '{print gensub(/.*\s+([0-9]{4}-[0-9]+-[0-9]+T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]+).*source-address="([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*destination-address="([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/, "(I) \\1\n(II) \\2\n(III) \\3", "g"); }' file
使用perl的另一种解决方案:
perl -lne 'print "(", "I" x ++$c, ") $_" for m/.*?\s+(\d{4}-\d+-\d+T\d{2}:\d{2}:\d{2}.\d+).*source-address="(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*destination-address="(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*/' file
输出:
(I) 2013-1-19T00:00:53.911
(II) 10.1.2.0
(III) 100.1.1.2