2016-04-17 3 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 

Первый столбец - это счетчик, второй ip: порт, третий статус.

То, что я хочу сделать, это переформатировать вывод так, что он выходит, как этот

   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

Вы хотите, чтобы группа по статусам, какова идея размера столбца? почему есть четыре столбца? четыре столбца статические? Так что, если это так, почему 17-го времени ожидания не находится в первом столбце вместо второго? Вы должны точно описать структуру выходных данных. – 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

Хе-хе, я думаю, ты справишься ;-) – 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 

Output (Если вы хотите белые пробелы вместо "\ т" в качестве разделителя, изменить delim="\t" к delim=" "):

 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-массива, и он не будет работать с входным файлом, который был отправлен OP, поскольку вы устанавливаете FS, который отключает поведение по умолчанию по умолчанию, игнорируя ведущие/завершающие пробелы. Если вы просто добавите '{gsub (/^[[: space:]] + | [[: space:]] + /," ")}' в начале, то он будет работать с данными OP. –

+1

@EdMorton: Спасибо за разъяснение! Я адаптировал свой ответ. –

+0

Вы должны действительно сказать gawk 4. * хотя, поскольку более ранние версии gawk не поддерживают синтаксис массива, который вы используете (или просто не используете этот синтаксис, а затем он будет работать в любом awk).Кроме того, вам не нужно помещать нулевые строки в конкатенацию строк - например, 'str = str '« delim »« key »может быть записано как« str = str delim key ». FInally, 'str = str" "delim" "(status [key] [k]? Status [key] [k]: 0)' может быть записано как «str = str delim status [key] [k] +0 '. –

Смежные вопросы