我有以下 tcpdump 流:
Current:
07:36:03.848461 IP 172.17.3.41.33101 > 172.17.3.43.17408: UDP, length 44
07:36:03.848463 IP 172.17.3.42.33101 > 172.17.3.43.17409: UDP, length 44
07:36:03.848467 IP SYSTEM-A.33101 > 172.17.3.43.17418: UDP, length 45
07:36:03.848467 IP SYSTEM-B.33101 > 172.17.3.43.17419: UDP, length 45
端口号是十进制的。如何将其通过管道传输到 sed 或 awk 以修改流,使其与端口号相同的流更改为十六进制:
Expected:
07:36:03.848461 IP 172.17.3.41.814d > 172.17.3.43.4400: UDP, length 44
07:36:03.848463 IP 172.17.3.42.814d > 172.17.3.43.4401: UDP, length 44
07:36:03.848467 IP SYSTEM-A.814d > 172.17.3.43.440a: UDP, length 45
07:36:03.848467 IP SYSTEM-B.814d > 172.17.3.43.440b: UDP, length 45
如果我有端口号,我会使用它来将其转换为十六进制:
echo 33101 | sed -e 's/.*://' | xargs printf "%x\n"
814d
我一直在尝试解决这个问题,但没有运气。如何'.'
在流的第三和第五列中最后一次出现后替换端口号,然后动态将其更改为十六进制?
与
perl
:它查找由一个空格 (
\s
) 后跟一个或多个(+
)非空格(\S
) 的序列、一个点和一个或多个数字 (\d+
) 的序列组成的单词,并替换结束部分(其开头标有\K
)用十进制$&
格式的相同 ( )x
(g
局部,替换被e
评估为 perl 代码)。在每个 UNIX 机器上的任何 shell 中使用任何 awk:
使用 GNU awk 将第三个参数匹配():
如果字段编号是恒定的 - 如您的问题字段 3 和 5 - 尝试
例如,字段 5 中的尾随冒号:
第一个应该问这是否明智,
172.17.3.43.440a
前 4 个句点分隔的字段是十进制的,而第 5 个是十六进制的看起来很奇怪。但是,让我们假设 OP 有充分的理由。OP 为我们提供了一些示例数据和所需的输出,这非常有帮助。
OP 向我们展示了
echo 33101 | sed -e 's/.*://' | xargs printf "%x\n"
这让我们对他们的思维过程有了一些了解。这告诉我他们走错了路。他们想以某种方式分解线路(使用awk
或sed
基于标签),printf
将其转换为十六进制,然后重新组装线路。对每一行重复。虽然显然这可以工作,但它非常慢。Unix 和 Linux 进程很便宜,但不是免费的。这种方法每行将使用许多进程,并且 tcpdump 流输出预计会有数百行。最好对每个文件只使用几个进程进行更改,因此如果可能的话,这具有合理的速度。所以关于工具的选择。标签建议
sed
和awk
。我会拒绝sed
。它是turing complete
(假设有无限量的内存),因此可以做任何其他语言可以做的事情,但这并不意味着它会很容易或可读。如果我这样做,我可能会使用perl
orpython
,但这awk
是完全合理的,所以让我们使用它。awk
程序自己循环遍历行,所以这是一个好的开始。OP 谈到了,third column
但在查看所需的输出时,他们也想要第五个。他们不希望将第一列中的毫秒转换为十六进制,尽管那也是一个数字after last occurrence of '.'
。所以有一个选择,我们是在第一列之后循环遍历每一列(在 awk 中称为“字段”)还是只执行第三和第五列?要么工作。让我们采取一般情况并完成所有列。这给了我们现在我们需要查看该字段是否匹配
.
后跟一个数字,然后是一个可选:
字段(因此我们转换原始数据中的第 5 个字段)。这可以通过正则表达式来完成,这是 Unix 推广的强大思想之一。所以现在要做转换。用于
match
分解模式,sprintf 将其放回,得到最终程序谢谢大家的回答!他们都工作!但是我也想在这里发布我的解决方案。现在我知道我特别要求
sed
和awk
为此,但我的输入是一个tcpdump
流,我想将端口号修改为十六进制。所以我浏览了源代码并更改了以下几行:(void)snprintf(buf, sizeof(buf), "%u", i);
至
(void)snprintf(buf, sizeof(buf), "%u", i);
至
编译二进制文件,现在 tcpdump 以十六进制打印端口。