2016-04-17 10 views
3

いくつかの異なる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 

最初の列はカウント、2番目のip:port、3番目のステータスです。私が何をしたいか

が、それはこの

   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で実現することは可能ですか?誰かがこれを得る方法の例を持っていますか?

申し訳ありません申し訳ありませんが、入出力結果を貼り付けるのに苦労しましたが、これは今のところです。 ありがとうございます。ここで

+0

あなたの質問は面白くないかもしれませんが、それは明らかではありません。今何を持っているかのように展開してください。どうやってそれを形にしたいですか? –

+0

ステータス別にグループ化したい、列サイズの背景にあるアイデアは何ですか?なぜ4つの列があるのですか?静的な4列ですか?だから、それがなぜ時間待っているの17が2番目の列の代わりに最初の列にないのですか?結果出力の構造を正確に記述する必要があります。 – FZE

+0

私は少し理解しています、列のサイズはuniqeポート数です。私の質問に気をつけてください。 – FZE

答えて

1
$ 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 
+1

あなたは私の新しい「awk」先生です。 – totoro

+0

さて、私は先月かなり仕事をしていました。もしそれが給料のポジションなら、私はすべて耳にします:-)。 –

+1

Heh、私はあなたが管理すると思う;-) – totoro

0

グラム AWK-ソリューションは

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=" "への変更delim="\t"の)です:

 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 
+0

あなたはgawk 4. *が真の2d配列のために必要であると言及する必要があります。また、FSを設定しているため、OPがポストした入力ファイルで動作しません。開始時に '{gsub(/^[[:space:]] + | [[:space:]] + /、")} 'を追加すると、OPsデータで動作します。 –

+1

@エドモトン:説明をありがとう!私は私の答えに適応しました。 –

+0

gawkの以前のバージョンでは、使用している配列構文をサポートしていない(またはその構文を使用しないで、どんなawkでも使える)のでgawk 4 *と言うべきです。また、文字列連結にヌル文字列を入れる必要はありません。例えば、 'str = str" "delim" "key'は単に' str = str delim key'と書くことができます。 'str = str '" delim ""(状態[key] [k]?status [key] [k]:0) 'は単に' str = str delim status [key] [k] +0として書くことができます'。 –