Script Para Formatação de Texto Com Cabeçalho, Rodapé e Campos de Dados Originados de Arquivo em AWK

Publicado por Perfil removido (última atualização em 31/07/2012)

[ Hits: 7.100 ]

Download format001.awk

Download 1343706392.format001.awk (versão 2)




Este script faz uma coisa relativamente simples:

-  recebe um arquivo com linhas de texto;
- separa as primeiras linhas como uma espécie de cabeçalho, conforme recebidas;
- as linhas seguintes são agrupadas de n em n linhas numa única mesma linha;
- deixa as últimas linhas sem serem agrupadas, como um rodapé;

Deve ser habilitada a execução com "chmod +x ./format001.awk"

$ ./format001.awk -v header=nnn1 -v footer=nnn2 -v step=nnn3 <arquivo>

ou

$ ./format001.awk --assign=header=nnn1 --assign=header=footer=nnn2 --assign=header=step=nnn3 <arquivo>

Onde:

- header: quantidade de primeiras linhas chamadas aqui como cabeçalho;
- footer: quantidade de últimas linhas chamadas aqui como rodapé;
- step: quantidade de linhas a serem unidas numa mesmo linha a cada vez;

Há possíveis variações, como não agrupar apenas as últimas linhas, apenas  que não puderem completar o número de linhas máximo permitido numa linha criada na saída do programa.

Não consegui ainda descobrir como o script pode detectar que não há um arquivo de entrada. Se não houver nome de arquivo, ele entra em loop saindo apenas com Ctrl+C ou semelhante.

Porém há outra situação em que a entrada não possui um nome de arquivo e que o script recebe via pipe "|", por exemplo.

Nos dois casos, redirecionamento e estar sem nome de arquivo de entrada mesmo, o AWK interpreta o nome do arquivo de entrada como o caractere "-".

Como saber em qual caso "-" é um pipe e em qual caso é uma falha?

Fora isto talvez haja um caso ou outro não-previsto de falha na passagem de parâmetros sem tratamento de erro pelo script.

  



Versões atualizadas deste script

Versão 2 - Enviado por euteste da silva em 31/07/2012

Changelog: Modificações na entrada de dados e no if(!$0)

Download 1343706392.format001.awk


Esconder código-fonte

#!/usr/bin/awk -f

################################################################################
#
#  Deve ser habilitada a execucao com "chmod +x ./format001.awk"
#  O nome do programa deve ser alterado no codigo em caso de ser renomeado.
#
#  Uso:
#
#   $ ./format001.awk -v header=nnn1 -v footer=nnn2 -v step=nnn3 <arquivo>
# ou   $ ./format001.awk --assign=header=nnn1 --assign=header=footer=nnn2 --assign=header=step=nnn3 <arquivo>
#
#   -v eh opcao para passar valores a variaveis de script por linha de comando
#   --assign eh equivalente a opcao -v
#
#   * header eh o numero de linhas de cabecalho
#   * footer eh o numero de linhas de rodape
#   * step eh o numero de linhas a ser escrito como unica linha antes de uma quebra de linha
#
#   nnn1, nnn2, nnn3 sao valores numericos diferentes a serem passados 
#   <arquivo> eh o arquivo a ser formatado pelo script
#
#   Em caso de omissao de um dos valores, o dafault eh 0.
#
#
#
################################################################################


BEGIN   {

      if (header=="") header = 0;
      if (footer=="") footer = 0;
      if (step=="") step = 0;

      h_=header;
      f_=footer;
      s_=step;

      gsub(/[[:digit:]]/,"",h_);
      gsub(/[[:digit:]]/,"",f_);
      gsub(/[[:digit:]]/,"",s_);

      if (h_ || f_ || s_) {

         print "\n\tErro: uma das variaveis eh negativa ou eh um numero.\n\n\tUso:\n\n\
      $ ./format001.awk -v header=nnn1 -v footer=nnn2 -v step=nnn3 <arquivo>\n\
    ou   $ ./format001.awk --assign=header=nnn1 --assign=footer=nnn2 --assign=step=nnn3 <arquivo>\n\n\
      -v eh opcao para passar valores a variaveis de script por linha de comando\n\
      --assign eh equivalente a opcao -v\n\n\
      * header eh o numero de linhas de cabecalho\n\
      * footer eh o numero de linhas de rodape\n\
      * step eh o numero de linhas a ser escrito como unica linha antes de uma quebra de linha\n\n\
      nnn1, nnn2, nnn3 sao valores numericos diferentes a serem passados\n\
      <arquivo> eh o arquivo a ser formatado pelo script\n\n\
      Em caso de omissao de um dos valores, o dafault eh 0.\n";

         exit;
      }


   }

   {

      if (!$0) exit;
      linhas[cont++]=$0;
   }

END   {


      for(i=0;i<cont;i++){

         printf ("%s",linhas[i]);

         if (i<header || i>=cont-footer-1) printf ("%c","\n");

         else {
            if (step==0)
               printf ("%c",(i<=cont-footer-1)?" ":"");
            else 
               printf ("%c",(i-header)%step<step-1?" ":"\n");

         }

      }

   }

Scripts recomendados

Pesquisa de grupos do sistema por nome ou GID em AWK

Regressão linear usando Shell Bash + AWK

Mostrar as partições existentes no HD

Mostrar as partições existentes no HD

Utilização de memória swap no Solaris ( swap memory utilization in Solaris )


  

Comentários
[1] Comentário enviado por foxbit3r em 30/07/2012 - 21:06h

Olá,

Eu rodei o seu script e não consegui visualizar a criação de cabeçalho e rodapé.
Vc poderia por favor postar um exemplo?

Obrigado.

[2] Comentário enviado por removido em 30/07/2012 - 23:06h


[1] Comentário enviado por foxbit3r em 30/07/2012 - 21:06h:

Olá,

Eu rodei o seu script e não consegui visualizar a criação de cabeçalho e rodapé.
Vc poderia por favor postar um exemplo?

Obrigado.


BLZ!!!

Você é o cara que fez os scripts de AWK que tinha antes.

Bem, realmente não ficou muito claro o propósito.

Ele foi um teste para outras ideias, do tipo pegar "uma coisa" e transformar essa coisa em HTML.

Fiz pensando nos seguintes termos:

- a entrada são dados retirados de alguma saída, os quais possuem algum tipo de explicação nas primeiras linhas
Podem ser comentários mesmo

- as linhas seriam campos, mas campos sem estarem organizados na mesma linha como que registros.
Então ele pega as linhas de x em x linhas e as transforma numa única linha (que virou um registro) com x campos.
Dá prá colocar um separador de campos igual ao do /etc/passwd, que é o ":"

- por fim, a criação do rodapé, sem aglutinar as últimas linhas.
Para manter a ideia do "conjunto" do "todo", há a possibilidade de deixar algumas últimas linhas sem se transformarem numa mesma linha, caso haja necessidade.

Fiz um teste por aqui e há um problema com a linha 65:

if (!$0) exit;


Eu a comentei e a coisa funcionou.

if (!$0) exit;


Ela estava aí por causa daquela coisa de tentar sair do loop caso não haja entrada. Aí ela verificou um caracter zero e saiu.

O teste:

Peguei um modelo de passwd reduzido

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh


e modificado com o comando *"sed"*, para apenas auxiliar na construção de um possível exemplo; "sed" trocou o ':' por um '\n' para ficar com os dados espalhados daquela forma e com linhas de comentário ao inicio e ao fim apenas para exemplo (aqui este arquivo de entrada será chamado de passwd2):

# teste do script de awk
# usando um arquivo de modelo do /etc/passwd todo desmontado
# para reagupamento
root
x
0
0
root
/root
/bin/bash
daemon
x
1
1
daemon
/usr/sbin
/bin/sh
bin
x
2
2
bin
/bin
/bin/sh
sys
x
3
3
sys
/dev
/bin/sh
sync
x
4
65534
sync
/bin
/bin/sync
man
x
6
12
man
/var/cache/man
/bin/sh
lp
x
7
7
lp
/var/spool/lpd
/bin/sh
mail
x
8
8
mail
/var/mail
/bin/sh
news
x
9
9
news
/var/spool/news
/bin/sh
uucp
x
10
10
uucp
/var/spool/uucp
/bin/sh
proxy
x
13
13
proxy
/bin
/bin/sh
backup
x
34
34
backup
/var/backups
/bin/sh
# caso tenha dado certo
# estas deverao ser as duas ultimas linhas da saida


Então para reorganizar as informações usou-se a seguinte linha:

./format001.awk -v header=3 -v footer=2 -v step=7 passwd2


header para as três linhas com '#', footer para as duas últimas com '#' e step porque o passwd quando estava com o ':' possuia sete campos por linha.

A saída:

# teste do script de awk
# usando um arquivo de modelo do /etc/passwd todo desmontado
# para reagupamento
root x 0 0 root /root /bin/bash
daemon x 1 1 daemon /usr/sbin /bin/sh
bin x 2 2 bin /bin /bin/sh
sys x 3 3 sys /dev /bin/sh
sync x 4 65534 sync /bin /bin/sync
man x 6 12 man /var/cache/man /bin/sh
lp x 7 7 lp /var/spool/lpd /bin/sh
mail x 8 8 mail /var/mail /bin/sh
news x 9 9 news /var/spool/news /bin/sh
uucp x 10 10 uucp /var/spool/uucp /bin/sh
proxy x 13 13 proxy /bin /bin/sh
backup x 34 34 backup /var/backups /bin/sh
# caso tenha dado certo
# estas deverao ser as duas ultimas linhas da saida


Faltou o caracter "dois pontos", o ':' para separar os campos.

É um exercício de formatação de saída de texto. Pode ter sim outro modo melhor de se fazer com AWK.

Serve como preparativo para algo mais sério, um uso mais prático do AWK no dia a dia.

O separador de campo pode ser utilizado e o exemplo do que seria o cabeçalho/rodapé dependeria de quem usasse como ferramenta para outra coisa.

[3] Comentário enviado por foxbit3r em 31/07/2012 - 00:44h

fiz umas modificações no seu código e consegui entender agora o que vc quis fazer.

[4] Comentário enviado por foxbit3r em 31/07/2012 - 00:45h

Modicação:
[code]
BEGIN {
if( ARGC != 2 ) {
printf("Uso: %s <arquivo>\n", ARGV[0])
exit -1
}
[/code]

[code]

{
if ($0 ~ /^$/) exit;
linhas[cont++]=$0;
}
[/code]

[5] Comentário enviado por removido em 31/07/2012 - 01:20h


[4] Comentário enviado por foxbit3r em 31/07/2012 - 00:45h:

Modicação:
[code]
BEGIN {
if( ARGC != 2 ) {
printf("Uso: %s <arquivo>\n", ARGV[0])
exit -1
}
[/code]

[code]

{
if ($0 ~ /^$/) exit;
linhas[cont++]=$0;
}
[/code]


Obrigado pela colaboração, testar etc.

"if ($0 ~ /^$/) exit;" testa se não há coisa alguma entre o início e o fim da linha, então é linha vazia mesmo.

Agora o "if( ARGC != 2 ) " eu fiz uns testes em separado e se o script rodar recebendo redirecionaamento de pipe, se eu não me engano, não funciona.

Mas nesse minuto, apenas agora, tive uma ideia, se seria o caso de desativar o "if( ARGC != 2 ) " com outra opção enviada pelo -v para o caso de se poder usar com dados de pipe.

Quer dizer, numa situação qualquer.

Obrigado de novo!

[6] Comentário enviado por removido em 31/07/2012 - 18:51h

Tenho a impressão de que as tabulações do "help text" da segunda versão viraram espaços em branco e que isso pode causar algum problema.
Se for o caso, basta apenas reformatar o código.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts