1

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

数据如下所示:

/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,-> awk '{ print $4 \t $8 \t $10 }' 因为日志文件中的“device_name”后面有一些字段并不总是出现在所有日志行中,所以我必须使用分隔符,例如 awk -F 'source-address=' '{print $2}' | awk '{print $1} -> 这给出了 source-addressIP,即(II ) 要求

我不确定如何使用 awk 搜索 I、II 和 III 进行组合。

有人可以帮忙吗?

4

3 回答 3

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
于 2013-10-27T17:42:06.957 回答
1

你到底想要什么?

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

对于第一种情况,您可以使用您选择的脚本语言(我的将是 Perl)来解析该行,或者使用sed一个大替换的硬方法来解析该行。或者介于两者之间的东西——使用三个正则表达式来获得你想要的部分。

对于第二种情况,您可以调整任何以前的解决方案,最好是那个sed。awk 和 sed 解决方案已经发布。

对于第三种情况,您可以只运行awk您在问题中提到的明显解决方案,并将结果发送到单个管道,例如{ awk …; awk …; awk …; } < file | consumer.

于 2013-10-27T17:53:50.393 回答
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
于 2013-10-27T17:38:30.827 回答