shell script para fazer alguma manipulação de texto da estrutura de dados do arquivo de texto e pequenas alterações de conteúdo

1

Pedimos desculpas antecipadamente pela parede do texto, sem saber como representar a estrutura de dados existente.

Recebi cerca de um ano de registros coletados a cada hora em um servidor.

Infelizmente, corrigir o script de coleta de dados para que ele crie os arquivos da maneira que eles querem é fácil, mas ainda preciso converter os milhares de arquivos existentes. Eu estou encontrando algumas paradas aqui, e suspeito que seja além de minhas habilidades, ou estou mentalmente tornando isso mais difícil do que tem que ser.

Esta é a iteração base de uma das execuções (ela é executada a cada 5 minutos a cada hora)

2350
 id pool                 type rid rset                  min  max size used load
  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 0.00 6.25
  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.00 0.91
  0 pool_default         pset  -1 pset_default           24  66K   24 0.00 1.74

 id pool                 type rid rset                  min  max size used load
  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 5.01 6.21
  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.97 0.91
  0 pool_default         pset  -1 pset_default           24  66K   24 3.73 1.78

output truncated, but it goes on for 50 lines from the prior timestamp, until the next one.

Não sei como exibir números em uma cotação de bloco, mas cada corrida tem 50 linhas (todas são combinadas em um arquivo com aproximadamente 14400 linhas para cada dia, com o campo na frente de cada linha sendo a data derivada do nome do arquivo.

Aqui está o que eles querem que pareça. A posição de campo em termos de espaço em branco não parece importar, apenas a posição relativa do campo, incluindo o novo campo "int", que é mostrado iterando para 2, mas na verdade apenas itera uma vez a cada 50 linhas (a execução completa da coleta de dados) e depois começar de volta em 01.

date     hhmm int id pool                type rid rset                  min  max size used load
20121105 2350 01  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 0.00 6.25
20121105 2350 01  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.00 0.91
20121105 2350 01  0 pool_default         pset  -1 pset_default           24  66K   24 0.00 1.74

date     hhmm int id pool                type rid rset                  min  max size used load
20121105 2350 02  5 SUNWtmp_serverxd1z1      pset   1 SUNWtmp_serverxd1z1       104  104  104 5.01 6.21
20121105 2350 02  4 SUNWtmp_serverxd1z2      pset   2 SUNWtmp_serverxd1z2        16   16   16 0.97 0.91
20121105 2350 02  0 pool_default         pset  -1 pset_default           24  66K   24 3.73 1.78

Eu tentei alguns sed e awk one liners, mas cheguei à triste conclusão de que eu nunca tive que manipular texto de qualquer maneira que fosse mais complexa do que um 1 liner poderia manipular, e neste momento eu vejo esse arquivo precisando de algo mais complexo que isso.

exemplo de algo que tentei reproduzir com formato:

gawk -vdate=$DATE -vtime=$TIME '{print date " " time $0 }' ./poolstat_original_format.txt

usando data e hora derivadas do nome do arquivo nessas duas variáveis.

Minha experiência anterior com scripts de shell está relacionada à automação e à solução de problemas do sistema, nunca tive uma experiência real com essa movimentação de texto, portanto, se isso é realmente um problema fácil e estou pensando nisso, ótimo, útil comentários apreciados.

Informações adicionais que eu pretendia adicionar, mas me distanciei.

A data é derivada do nome do arquivo que está chegando. 20121003-poolstat_serverxd1z0.txt A hora é o numérico de 4 dígitos a cada 50 linhas.

O campo int precisa iterar toda vez que o poolstat for executado. Veja abaixo para detalhes.

Em resumo, os únicos campos que precisam ser alterados:

campo 1, a data de 8 dígitos, derivada do nome do arquivo IE: 20121003-poolstat_serverxd1z0.txt campo 2 o tempo de 4 dígitos que está dentro do arquivo a cada 50 linhas. campo 3 a contagem de iteração, como segue: Baseado nos dígitos 3 e 4 do tempo de 4 dígitos. 00-05-10-15-20-25-30-35-40-45-50-55 minutos de corrida.

01-02-03-04-05-06-07-08-09-10-11-12 iteração.

O resto é apenas imprimir os campos existentes, obtendo-os em uma linha, depois o comando awk (ou outro) para imprimir os outros 10 campos, tudo isso mantendo o controle da iteração atual.

E apenas para manter as coisas complexas, os campos na linha de cabeçalho também precisam de 3 novos campos:

date hhmm int

o resto dos campos são cabeçalhos fornecidos pelo poolstat.

    
por Logan Stout 06.05.2013 / 17:03

2 respostas

3

Com uma reserva referente à minha pergunta de comentário, isso deve funcionar:

awk -v date=20121105 'NF == 0 {print; next;};
  NF==15 && $2 == "id" {readvar=$1; for (i=1;i<15;i++) $i = $(i+1); NF=14; };
  NF==14 { if (block<2) block++; 
    concatvars=$1; for (i=2;i<11;i++) concatvars=concatvars " " $i;
    print "date hhmm int",concatvars,date,readvar,sprintf("%02d", block),"05"; };
  NF==10 {readvar2=$7;
    print $1,"pset 1",$1,$2,$3,$4,$5,$6,date,readvar,sprintf("%02d", block);};
  NF==15 { 
    print readvar2,$1,"pset 2",$1,$2,$3,$4,$5,$6,date,sprintf("%02d", block),$7;
    nextline=$8; for (i=9;i<15;i++) nextline=nextline " " $i; };
  NF==1 {print nextline,$1}' inputfile
    
por 06.05.2013 / 18:23
2

Parece que você precisa pegar o tempo desde o início do bloco e depois adicionar alguns campos a cada linha depois disso.

Não sei como a iteração deve ser feita, com base na sua descrição

awk -v date=20121105 '
    NF == 1 {time = $1; intv = intv%50 + 1; next}
    $1 == "id" {print "date", "hhmm", "int", $0; next}
    NF > 0 {$1 = date OFS time OFS sprintf("%02d", intv) OFS $1}
    1
' file

Se você quiser tornar a saída mais bonita, canalize o comando awk para column -t

    
por 06.05.2013 / 18:36