De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.


Bash - Colunador

Colaboração: Julio Cezar Neves

Data de Publicação: 18 de julho de 2017

É muito raro vermos um script Shell que trabalhe devidamente com as opções de stdin, stdout e stderr, ou seja, entrada primária, saída primária e saída de erros primária. O script a seguir, habilita a captura dos dados de entrada pelo pipe (|), por um redirecionamento da entrada (<) ou por passagem de parâmetro e manda os erros para a saída de erros padrão, o que permite redirecionar os erros para onde você desejar, ou até trancar a saída de erro (2>&-) para evitar essas mensagens.

$ cat colunador.sh 
#!/bin/bash
#  Recebe dados via pipe, arquivo ou passagem de parâmetros e
#+ os coloca em coluna numerando-os

if  [[ -t 0 ]]        # Testa se tem dado em stdin
then
	(($# == 0)) || {  # Testa se tem parâmetro
		echo Passe os dados via pipe, arquivo ou passagem de parâmetros >&2  # Redirecionando para stderr
		exit 1
	}
	Parms="$@"
else
    Parms=$(cat -)    # Seta parâmetros com conteúdo de stdin
fi 
set $Parms
for ((i=1; i<="$#"; i++))
{
    Lista=$(for ((i=1; i<="$#"; i++)); { printf "%0${##}i %s\n" $i "${!i}"; })
}
echo "$Lista" | column -c $(tput cols)
$ echo {A..Z} | colunador.sh
01 A   05 E   09 I   12 L   15 O   18 R   21 U   24 X
02 B   06 F   10 J   13 M   16 P   19 S   22 V   25 Y
03 C   07 G   11 K   14 N   17 Q   20 T   23 W   26 Z
04 D   08 H

Esse script começa testando se o FD 0 (zero), que é o descritor da entrada primária, está aberto em um terminal e isso ocorrerá se o programa não estiver recebendo dados por um pipe (|) ou por um redirecionamento de entrada (<). Assim sendo vamos testar se a quantidade de parâmetros passados ($#) é zero, ou seja: os dados não vieram por stdin nem por passagem de parâmetros quando então é indicado um erro, que é desviado para stderr (>&2).

Bem, agora vamos tratar os dados que recebemos, passando-os para a variável $Parms. Caso eles tenham vindo por passagem de parâmetros, aí é simples, é só atribuir a $Parms o valor de todos os parâmetros passados ($@).

Caso os dados tenham vindo de stdin, temos mais 2 macetes:

1. A quase totalidade dos utilitários do Shell, aceitam o hífen como representando os dados recebido de stdin. Veja isso:

$ cat arq
Isto é um teste
Outra linha de teste
$ echo Inserindo uma linha antes de arq | cat - arq
Inserindo uma linha antes de arq
Isto é um teste
Outra linha de teste

Ou seja, o comando primeiramente listou o que recebeu da entrada primária e em seguida o arquivo arq.

2. O outro macete é o comando set. Para entendê-lo vá para o prompt e faça:

$ set a b c
$ echo $1:$2:$3
a:b:c

Conforme você viu, este comando atribuiu os valores passados como os parâmetros posicionais.

Uma vez entendido isso, vimos que os valores recebidos de stdin foram colocados em $Parms que por sua vez teve seu conteúdo passado para os parâmetros posicionais, unificando dessa forma, os dados de qualquer tipo de entrada recebida.

O for terminará quando alcançar a quantidade de parâmetros passados ($#) e o comando printf, em seu primeiro parâmetro, (%0${##}d), diz que a linha será formatada (%) com um decimal (d) com ${##} algarismos, preenchido com zeros à esquerda (0).

Veja isso para entender melhor: ${#var} devolve o tamanho da variável var e também sabemos que $# retorna a quantidade de parâmetros passados. Juntando os dois, vemos que ${##} devolve quantos algarismos tem a quantidade de parâmetros. Faça este teste para você ver:

$ set {a..k}            # Passando 11 parâmetros
$ echo ${##} algarismos
2 algarismos
$ set a b c             # Passando 3 parâmetros
$ echo ${##} algarismos
1 algarismos

Uma vez montada a lista, é só passá-la para o comando tr, cuja opção -T diz que a formatação não é para impressora e o -8 é para dividir a saída em 8 colunas (trabalhar para que? O Shell já tem comando pronto para tudo!)

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Julio Cezar Neves