4

我有这个 iptable 日志:

Feb 25 10:32:48 XXX: [414645.555838] FW: DEN TCP IN=eth0 OUT= MAC=XYZ SRC=1.1.1.1 DST=2.2.2.2 LEN=40 TOS=0x00 PREC=0x00 TTL=57 ID=0 DF PROTO=TCP SPT=80 DPT=51814 WINDOW=0 RES=0x00 RST URGP=0

我想 grep 1.1.1.1 和 80(SRC 和 SPT 字段)。我这样做:

grep -oP 'SRC=([^ ]+).+SPT=([0-9]+)' /var/log/iptables.log

但它返回:

SRC=1.1.1.1 DST=2.2.2.2 LEN=40 TOS=0x00 PREC=0x00 TTL=57 ID=0 DF PROTO=TCP SPT=80

如何仅获得 $1 和 $2 (对匹配值的引用)?

4

2 回答 2

10

您的示例的主要问题是您正在尝试返回分组,这是不可能的 IIUC。解决此问题的一种方法是使用积极的后视(参见 参考资料man perlre):

grep -oP '(?<=SRC=|SPT=)[^ ]*'

输出:

1.1.1.1
80

这是一个更便携的替代方案:

grep -o 'SRC=[^ ]*\|SPT=[^ ]*' | grep -o '[^=]*$'

如果您希望输出在一行上,您应该考虑使用一种工具,即使用Lev 的答案。如果您知道输出总是成对出现,您可以将这些行加入paste

grep -oP '(?<=SRC=|SPT=)[^ ]*' | paste - -

或与xargs

grep -oP '(?<=SRC=|SPT=)[^ ]*' | xargs -n2

或者sed

grep -oP '(?<=SRC=|SPT=)[^ ]*' | sed 'N; s/\n/ /'
于 2013-02-25T13:47:34.167 回答
8

一种sed方法:

sed -rn 's/.*SRC=([^ ]+).*SPT=([0-9]+).*/\1 \2/p' /var/log/iptables.log

您可以将其通过管道传输while read src spt到您的脚本或类似的东西中。现在这当然不是很有效,因为模式中有三颗星,所以如果性能是一个问题,您可以考虑使用诸如cut提取某些字段之类的东西:

cut -d' ' -f12,21 /var/log/iptables.log

不确定日志格式是否足够一致以使其正常工作。

于 2013-02-25T13:18:48.907 回答