Linux 重新格式化输出打印
在几个不同的linux机器中,我必须计算tcp套接字连接的数量以及不同端口的状态。 最后,打印输出可能如下所示Linux 重新格式化输出打印,linux,awk,formatting,Linux,Awk,Formatting,在几个不同的linux机器中,我必须计算tcp套接字连接的数量以及不同端口的状态。 最后,打印输出可能如下所示 49570 10.10.10.10:13062 ESTABLISHED 783 10.10.10.10:18080 CLOSE_WAIT 493 10.10.10.10:18082 CLOSE_WAIT 109 10.10.10.10:18080 SYN_RECV 17 10.10.10.10:15062 TIME_WAIT 15
49570 10.10.10.10:13062 ESTABLISHED
783 10.10.10.10:18080 CLOSE_WAIT
493 10.10.10.10:18082 CLOSE_WAIT
109 10.10.10.10:18080 SYN_RECV
17 10.10.10.10:15062 TIME_WAIT
15 10.10.10.10:15062 ESTABLISHED
第一列是计数,第二列是ip:port,第三列是状态
我想做的是重新格式化输出,使其变成这样
13062 15062 18080 18082
ESTABLISHED 49570 15 0 0
CLOSE_WAIT 0 0 783 493
SYN_RECV 0 0 109 0
TIME_WAIT 0 17 0 0
ip在不同的机器之间是不同的,可能有更多的端口,或者更多的状态,或者更少。
是否有可能通过awk实现这一点。有没有人能举例说明如何做到这一点
很抱歉,我很难粘贴所需的输入/输出结果,现在与上面一样。
非常感谢。$cat tst.awk
$ cat tst.awk
{
sub(/.*:/,"",$2)
ports[$2]
statuses[$3]
counts[$2,$3] = $1
for (i=1;i<=NF;i++) {
maxWidth[i] = (length($i) > maxWidth[i] ? length($i) : maxWidth[i])
}
}
END {
statusWidth = maxWidth[3]
otherWidth = (maxWidth[1] > maxWidth[2] ? maxWidth[1] : maxWidth[2]) + 2
printf "%-*s", statusWidth, ""
for (port in ports) {
printf "%*s", otherWidth, port
}
print ""
for (status in statuses) {
printf "%-*s", statusWidth, status
for (port in ports) {
printf "%*d", otherWidth, counts[port,status]
}
print ""
}
}
$ awk -f tst.awk file
13062 15062 18080 18082
SYN_RECV 0 0 109 0
CLOSE_WAIT 0 0 783 493
ESTABLISHED 49570 15 0 0
TIME_WAIT 0 17 0 0
{
子(/.*:/,“”,$2)
港口[$2]
状态[$3]
计数[$2,$3]=$1
对于(i=1;i最大宽度[i]?长度($i):最大宽度[i])
}
}
结束{
statusWidth=maxWidth[3]
otherWidth=(maxWidth[1]>maxWidth[2]?maxWidth[1]:maxWidth[2])+2
printf“%-*s”,statusWidth“
用于(端口中的端口){
printf“%*s”,其他宽度,端口
}
打印“”
用于(状态中的状态){
printf“%-*s”,状态宽度,状态
用于(端口中的端口){
printf“%*d”,其他宽度,计数[端口,状态]
}
打印“”
}
}
$awk-f tst.awk文件
13062 15062 18080 18082
同步记录0 0 109 0
关闭\u等待0 783 493
成立495701500
等待时间0 17 0 0
这里是另一个gawk解决方案
awk -F"[: ]+" 'BEGIN{delim="\t"}
{ports[$3]; status[$3][$4]=$1; st[$4]}
END{str=delim
for(key in ports){str=str""delim""key}
print str
for(k in st){
str =k
for (key in ports) {
str = str""delim""(status[key][k] ? status[key][k] : 0)
}
print str
}
}' test.txt
输出(如果希望使用空格而不是“\t”作为分隔符,请将delim=“\t”
更改为delim=“
):
对于该输入(即,没有前导空格):
你的问题可能有点有趣,但并不清楚。你能像现在这样展开吗?你想如何塑造它?你想按状态分组,列大小背后的想法是什么?为什么有四列?四列是静态的吗?如果是这样,为什么时间等待的17不在第一列而不是第二列?您应该精确地描述结果输出的结构。好的,我了解一点,列大小是uniqe端口计数。别提我的问题。编辑粘贴结果时遇到一些问题,端口数不是固定的。它可以是更多,甚至更少,谢谢。那么您希望每个IP/主机都有第二个这样的输出吗?您应该提到这需要gawk 4。*由于真正的2d数组,它不能与OP发布的输入文件一起工作,因为您设置了FS,这会禁用awks忽略前导/尾随空格的默认行为。如果您只是在开始时添加
{gsub(/^[:space:][]+|[:space:][]+/,“”)}
,那么它就可以处理OPs数据了。@EdMorton:谢谢您的澄清!我已经修改了我的答案。你真的应该说gawk 4.*尽管gawk的早期版本不支持你正在使用的数组语法(或者只是不使用该语法,然后它就可以在任何awk中工作)。此外,您不需要在字符串串联中放入空字符串-例如,str=str“delim”键
可以写成只str=str delim键
。最后,str=str“delim”“(status[key][k]?status[key][k]:0)
可以写成只需str=str-delim status[key][k]+0
。非常感谢你的帮助。我上个月刚刚完成了我的工作,所以如果那是一个有报酬的职位,我会全神贯注:-)。非常感谢Ed,这很好。非常感谢。嗨,爱德。对不起,我是新来的。我认为你的答案是有用的。但我不确定我是否做对了。我点击了你答案上的“^”。请告诉我这是不是正确的方法。
15062 13062 18080 18082
SYN_RECV 0 0 109 0
CLOSE_WAIT 0 0 783 493
ESTABLISHED 15 49570 0 0
TIME_WAIT 17 0 0 0
49570 10.10.10.10:13062 ESTABLISHED
783 10.10.10.10:18080 CLOSE_WAIT
493 10.10.10.10:18082 CLOSE_WAIT
109 10.10.10.10:18080 SYN_RECV
17 10.10.10.10:15062 TIME_WAIT
15 10.10.10.10:15062 ESTABLISHED