将awk搜索与标准awk和awk分隔符相结合

时间:2013-10-27 17:25:08

标签: awk

我正在处理一组数据,我需要将特定字段作为输出:

数据如下所示:

/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进行组合。

有人可以帮忙吗?

3 个答案:

答案 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)

你到底想要什么?

  • 使用任何(合理标准的)工具解决问题
  • 使用awk
  • 的一个实例解决此挑战
  • 使用awk解决问题,无论花费多少实例

对于第一种情况,您可以使用您选择的脚本语言解析该行(我的是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 -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