Linux 重新格式化输出打印

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

在几个不同的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 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