Imprimir colunas de dados que envolvem internamente

2

Estou imprimindo alguns dados de monitoramento de um log como tal:

printf " %10s %5s %25s %15s %15s %s${txtrst}\n" $date $time $metric $status $current_criticality "$failure"

Eu gostaria que a última coluna, que não tem um comprimento definido, seja colocada dentro de seus limites, dos quais o lado esquerdo é claramente definido e o lado direito é onde quer que a tela esteja (local de quebra normal). Eu tentei definir o comprimento, mas isso não resolveu isso.

Exemplo da saída atual:

09/30/2015 14:39         execution        (SUCCESS)           SUCCESS
09/30/2015 14:34         execution         (FAILED)             ERROR  Step 3: Match Failed Blah blah blah blah blah blah blah.
09/30/2015 14:34         execution         (FAILED)           SUCCESS  Step 1: Match Failed Blah blah blah blah blah blah blah.
09/30/2015 14:34        round_trip         (10.174)             ERROR  Step 1: Match Failed Blah blah blah blah blah blah blah.
09/30/2015 14:34        round_trip         (10.174)           SUCCESS  Step 1: Match Failed Blah blah blah blah blah blah blah.
09/30/2015 13:30        round_trip         (94.652)             ERROR
09/30/2015 13:30        round_trip         (94.652)           SUCCESS
09/30/2015 13:19        round_trip          (0.257)           SUCCESS
09/30/2015 13:16        round_trip        (110.012)             ERROR
09/30/2015 13:16        round_trip        (110.012)           SUCCESS

Eu adoraria ver:

09/30/2015 14:39          execution       (SUCCESS)           SUCCESS
09/30/2015 14:34          execution        (FAILED)             ERROR  Step 3: Match Failed 
                                                                       Blah blah blah blah 
                                                                       blah blah blah.
09/30/2015 14:34          execution        (FAILED)           SUCCESS  Step 1: Match Failed 
                                                                       Blah blah blah blah 
                                                                       blah blah blah.
09/30/2015 14:34         round_trip        (10.174)             ERROR  Step 1: Match Failed 
                                                                       Blah blah blah blah 
                                                                       blah blah blah.
09/30/2015 14:34         round_trip        (10.174)           SUCCESS  Step 1: Match Failed 
                                                                       Blah blah blah blah    
                                                                       blah blah blah.
09/30/2015 13:30         round_trip        (94.652)             ERROR
09/30/2015 13:30         round_trip        (94.652)           SUCCESS
09/30/2015 13:19         round_trip         (0.257)           SUCCESS
09/30/2015 13:16         round_trip       (110.012)             ERROR
09/30/2015 13:16         round_trip       (110.012)           SUCCESS

muito parecido com um relatório da formatação de colunas do SQL * PLUS: col $ column format a15

Agradecemos antecipadamente por qualquer ideia!

    
por krmarshall87 30.09.2015 / 20:32

3 respostas

2

Aqui está uma kluge que funciona apenas porque é a última coluna:

  1. printf da primeira parte da linha (tudo exceto $failure , incluindo o espaçamento), sem a nova linha à direita.
  2. echo "$failure" | fold -s -w $desired_width | sed -e "2,\$s/^/$spacing/"

Onde $desired_width é a largura da coluna $failure e $ espaçamento é um monte de espaços para fazer a segunda linha (terceira, etc.) começar no ponto certo. Você poderia gerar esses espaços facilmente com algo como spacing=$(echo $'\t' | pr -Te71) . O 71 deveria funcionar, se eu contasse direito ...

Isso faz com que fold realize uma quebra de linha, então sed adiciona espaçamento (para alinhamento) à segunda coluna e subseqüentes. Quando impressa, a primeira linha se juntará à outra saída (devido à falta de nova linha).

Se eu quisesse fazer isso da maneira certa, o Perl tem vários módulos (por exemplo, Text::ASCIITable , Text::SimpleTable , Text::TabularDisplay que deve ser capaz de fazer isso.

    
por 30.09.2015 / 21:25
1

Há provavelmente algo que já existe, mas ...

awk -v cols=$(tput cols) '
    NR == 1 {
        prefix = gensub(/^(([[:blank:]]*[^[:blank:]]+){5}).*/, "\\1", 1, $0)
        prefix_width = length(prefix) + 2
        diff = cols - prefix_width
    }
    NF == 5 { print; next }
    {
        prefix = substr($0, 0, prefix_width)
        text = substr($0, prefix_width+1)
        while (length(text) > diff) {
            for (i=diff; i>0; i--) {
                char = substr(text,i,1)
                if (char == " " || char == "-") break
            }
            if (i == 0) i = diff  # no spaces or hyphens, break mid-word
            printf "%*s%s\n", prefix_width, prefix, substr(text,0,i);
            text = substr(text,i+1)
            prefix = ""
        }
        if (text) printf "%*s%s\n", prefix_width, prefix, text
    }
' file
    
por 30.09.2015 / 21:23
0

A maneira mais difícil é depois de reformatar como

indent='                                                                      '
sed "s/.\{$((${#indent}+2)),$COLUMNS\} /&\n$indent /;P;D"

(onde indent é 70 espaços == 10 + 5 + 25 + 15 + 15 do comando printf )
Mas a pré-formatação é melhor:

indent='                                                                      '
mapfile failure < <(fold -s -w $(($COLUMNS-${#indent}-1)) <<<"$failure")
printf "%10s%5s%25s%15s%15s" $date $time $metric $status $current_criticality
printf " %b$indent" "${failure[@]}\c"
    
por 30.09.2015 / 21:31

Tags