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.
Colaboração: Julio Cezar Neves
Data de Publicação: 05 de outubro de 2019
IMPORTANTE: As inscrições para a última turma do ano do curso Programação Shell Linux do Prof. Julio Neves se esgotam em breve, no dia 7 de outubro, às 23h59m. Clique aqui para saber mais e reservar a sua vaga.
Nessa série de artigos sobre redirecionamento, já foram mostrados diversos macetes dentre os quais destaco a forma de se mandar uma mensagem para a saída de erros (StdErr) e não para a tela, como é comum (mas incorreto) vermos.
Complementando isso hoje veremos o que se deve fazer para nosso script receber dados pela entrada primária ou pelas áreas de transferência.
Testamos a entrada primária com a opção -t 0
do comando test
, que será verdadeira se não houver dado em StdIn. A opção -t
é para testar file descriptors (que analisamos nos 4 artigos anteriores) e zero (0) é o file descriptor padrão da entrada primária (StdIn).
Sabemos que comandos no interior de parênteses criam um subshell para a execução, como se formassem um script, então para demonstrar o uso do test
com exemplos curtos, usarei esta técnica para emular scripts. Para começar, veja isso:
$ ([[ -t 0 ]] && echo StdIn vazia || echo Existem dados em StdIn)
StdIn vazia
Essa linha de comandos deve ser entendida como: se não houver dados em StdIn imprima StdIn vazia, caso contrário Existem dados em StdIn. Como não pusemos nada na entrada, funcionou do jeito que queríamos.
Então vamos mandar dados via pipe (|
):
$ echo Uma frase | ([[ -t 0 ]] && echo StdIn vazia || echo Existem dados em StdIn)
Existem dados em StdIn
Passando dados via Here Strings e recuperando-os:
$ ([[ -t 0 ]] && echo StdIn vazia || echo "$(cat -)" está em StdIn) <<< "A B C"
A B C está em StdIn
E o mesmo valeria se tivéssemos um arquivo na entrada:
$ cat x Linha1 de teste Linha2 de teste $ ([[ -t 0 ]] && echo StdIn vazia || echo "$(cat -)" está em StdIn) < x Linha1 de teste Linha2 de teste está em StdIn
Já vimos o conteúdo do arquivo x
agora veja isso:
$ echo Linha0 de teste | cat - x
Linha0 de teste
Linha1 de teste
Linha2 de teste
Ou com Here Strings:
$ cat - x <<< "Linha0 de teste"
Linha0 de teste
Linha1 de teste
Linha2 de teste
Ou seja, o cat -
lista tudo o que vem da entrada primária e foi por isso que usamos o $(cat -)
no nosso exemplo. Essa construção agregaria os parâmetros recebidos, antes de imprimir a linha.
O test -t FDn
serve para qualquer file descriptor independente do inteiro em FDn
. Vamos brincar com a saída de erros (FDn = 2
). Suponha que eu queira mandar uma mensagem para a saída de erros e em seguida dar um read
para que o usuário confirme ter lido a mensagem. Seria assim:
$ (echo Deu erro >&2; read)
Deu erro
Aparentemente funcionou, pois deu a mensagem e ficou esperando um <ENTER>
mas e se a saída for redirecionada para um arquivo, para /dev/null
ou for trancada (2>&-
)? Nesses casos não haveria nenhuma mensagem mas o programa ficaria parado esperando um <ENTER>
. Então o correto seria se só fizéssemos o read
se não houvesse desvio na StdErr. Ficaria assim:
$ (echo Deu erro >&2; [[ -t 2 ]] && read)
Dessa maneira, em qualquer dos casos descritos acima, ele não daria a mensagem nem executaria o read
. Experimente.
Consolidando tudo que vimos até aqui nessa série de artigos, vou te mostrar uma forma de pegar o dado de entrada por qualquer meio que ele venha. Aconselho entendê-lo e, se quiser, transformá-lo em uma função para usar em seus scripts.
$ cat test_stdin.sh
#!/bin/bash
#
# Para saber se tem dado na entrada primária
#
if [[ -t 0 ]] # Verdadeiro se não houver dados em StdIn
then
if (($# == 0)) # Então testa se foram passados parâmetros
then
echo Não tem dados na StdIn nem parâmetros >&2
exit 1
fi
Meio="por passagem de parâmetros" # Como os dados vieram?
else
Parms=$(cat -) # O que veio pela StdIn vai para $Parms
set "$Parms" # Os dados de Parms viram parâmetros posicionais
Meio="pela entrada primária" # Como os dados vieram?
fi
echo -e "Recebi $Meio os seguintes dados:\n$@"
No próximo e último artigo deste séria mostrarei como mandar/receber dados para/de as áreas de transferência
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários