Analisando dados em coluna

4

Eu tenho alguns dados em coluna que gostaria de formatar um pouco mais. Parece assim:

$ getStats | grep ESTABLISHED | column -t
all  tcp  117.54.56.131:80       <-  10.42.100.211:63752   ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752    ->  219.224.67.112:31180  ->                       137.51.59.141:80       ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443      <-  10.42.100.117:59999   ESTABLISHED:ESTABLISHED

Essencialmente, antes de chamar o column -t , quero mover o estado do TCP, 'ESTABLISHED: ESTABLISHED', na primeira e terceira linha, para que ele seja colocado corretamente na segunda linha. Como eu iria sobre isso? Usando awk e printf parece um pouco confuso aqui. Essencialmente, quero alinhar todas as colunas e alinhar à direita apenas a última coluna.

    
por atx 12.06.2013 / 07:01

3 respostas

2

O problema real aqui é que o número de colunas não é igual . Você tem algumas linhas com seis colunas e outras com oito.

Então, o que você precisa fazer é adicionar um campo x-th e y-th vazio onde eles estão faltando (x e y podem ser 5 e 6, ou talvez 3 e 4).

Você poderia fazer assim:

F="\(\S\S*\)\s*\s"
# This is 0160, a nonbreaking space
G=" "

| sed -e "s/^$F$F$F$F$F$F*$/\1 \2 \3 \4 \5 $G $G \6/g" \
| column -t

sed identifica essas linhas com apenas seis campos e adiciona dois campos extras, conforme apropriado. Com o exposto, recebo

all  tcp  117.54.56.131:80     <-  10.42.100.211:63752                         ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  ->  219.224.67.112:31180  ->  137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <-  10.42.100.117:59999                         ESTABLISHED:ESTABLISHED
    
por 21.06.2013 / 13:28
3

EDIT 1:

Um caminho pode ser algo como:

getStats | grep ESTABLISHED | column -t | sed \
-e 's/\(<-\|->\)[ ]\+/ /g' \
-e 's/[ ]\+\([^ ]\+$\)/\t/' | column -t -s "   "
                                               ^--- TAB
all  tcp  117.54.56.131:80     <- 10.42.100.211:63752                        ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  -> 219.224.67.112:31180  -> 137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <- 10.42.100.117:59999                        ESTABLISHED:ESTABLISHED

Primeiro, usando column -t , em seguida, removendo todos os espaços consecutivos após <- e -> com um espaço, em seguida, separando a última coluna com tab e fazendo um novo column -t -s '<TAB>'

Se na linha de comando: -s " Ctrl + V TAB " (também conhecido como tab ) como separador para column . Opcionalmente, use tr para substituir tabulações de espaços primeiro.

Definindo sed para uma operação e pulando grep e algumas outras modificações:

getStats | column -t | \
sed '/ESTABLISHED/!d;s/\(<-\|->\) */  /g;s/ *\([^ ]*\)$/\t /' | \
column -t -s "    "
                ^--- TAB

EDIT 2:

Mesmo que você encontre awk e printf messy, dou isso como uma opção. Com esse script, você pode dizer:

getStats | scrip_name ESTABLISHED

Uma vantagem é a flexibilidade de personalizar, etc.

Qualquer que seja a maneira de ver um deles, é necessário analisar os dados duas vezes ou salvar metadados sobre dados e imprimir no final.

Em suma, o que faz é:

  • Gravar a largura máxima de cada coluna.
  • Registrar o número máximo de colunas.
  • Salve cada campo em uma matriz em linha.
  • Ao final, imprima cada campo, mas use a largura máxima para essa coluna.
  • Preencha até colunas máximas - 1 com espaços.
  • Imprimir o último campo.

(A divisão entre awk -v pat="$1" ' e restante do código é apenas devido ao comentário HTML de destaque personalizado nesta página)

#!/bin/bash

# Argument 1 is what to match against.
awk -v pat="$1" '
# Iff match pat.
$0 ~ pat {
    # Highest number of columns.
    if (NF > cols)
        cols = NF
    # Increment number of lines.
    ++nl
    # Number of fileds on this line.
    lines[nl] = NF

    for (i = 1; i <= NF; ++i) {
        # IFF not last field and 
        # width of field is > current width of column, store it in wc_a.
        if (i < NF && (wc = length($i)) > wc_a[i])
            wc_a[i] = wc
        # Save columns in array lines[LINE COLUMN]=FIELD_DATA.
        lines[nl,i] = $i
    }
}

END {
    # Loop lines.
    for (i = 1; i <= nl; ++i) {
        # Print all but last.
        for (j = 1; j < lines[i]; ++j)
            printf("%-*s ", wc_a[j], lines[i,j])
        # Print "missing" columns.
        for (; j < cols; ++j)
            printf("%-*s ", wc_a[j], "")
        # Print last column field.
        printf("%s\n", lines[i,lines[i]])
    }
}
' "$2"
# $2 is either file or empty: expect pipe.

OLD:

Excluído e encontrado aqui

    
por 12.06.2013 / 08:01
1

Aqui está um pequeno script Perl para conseguir o que você quer:

$ getStats | grep ESTABLISHED | \
perl -ne '
chomp @a;
@a = split(" ",$_);
map { print "$_," } @a[0..4];
if ($a[5] !~ m/>/) {
  map { print " , ,$_," } @a[5..$#a];
  print "\n";
} else {
  map { print "$_," } @a[5..$#a];
  print "\n";
}
' | column -t -s ','

Resultados nesta saída:

all  tcp  117.54.56.131:80     <-  10.42.100.211:63752                         ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  ->  219.224.67.112:31180  ->  137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <-  10.42.100.117:59999                         ESTABLISHED:ESTABLISHED

Adotei uma abordagem ligeiramente diferente com o column -t e modifiquei minha saída do Perl para que ela introduzisse uma vírgula "," entre cada campo. Então, a saída antes do comando 'column é assim:

all,tcp,117.54.56.131:80,<-,10.42.100.211:63752, , ,ESTABLISHED:ESTABLISHED,
all,tcp,10.42.120.201:63752,->,219.224.67.112:31180,->,137.51.59.141:80,ESTABLISHED:ESTABLISHED,
all,tcp,77.221.237.24:443,<-,10.42.100.117:59999, , ,ESTABLISHED:ESTABLISHED,

O column -t -s ',' , então, coaxe column para dividir os caracteres separadores, o que eu acho mais fácil de tratar do que os espaços em branco simples.

A introdução das vírgulas por cada linha parece um pouco hacky para mim, mas faz o trabalho, isso poderia ser simplificado ainda mais, mas é uma solução funcional.

    
por 22.06.2013 / 18:59