Estou trabalhando em um script bash que analisa um arquivo separado por tabulação. Se o arquivo contiver a palavra "prompt", o script deverá solicitar que o usuário insira um valor.
Parece que durante a leitura do arquivo, o comando "read" não é capaz de ler a partir da entrada padrão, pois o "read" é simplesmente ignorado.
Alguém tem uma solução para fazer tanto a leitura de um arquivo quanto de stdin?
Observação: o script deve ser executado no Git Bash e no MacOS.
Abaixo está um pequeno exemplo de código que falha:
#!/bin/bash
#for debugging
set "-x"
while IFS=$'\r' read -r line || [[ -n "$line" ]]; do
[[ -z $line ]] && continue
IFS=$'\t' read -a fields <<<"$line"
command=${fields[0]}
echo "PROCESSING "$command
if [[ "prompt" = $command ]]; then
read -p 'Please enter a value: ' aValue
echo
else
echo "Doing something else for "$command
fi
done < "$1"
Resultado:
$ ./promptTest.sh promptTest.tsv
+ IFS=$'\r'
+ read -r line
+ [[ -z something else ]]
+ IFS=' '
+ read -a fields
+ command=something
+ echo 'PROCESSING something'
PROCESSING something
+ [[ prompt = something ]]
+ echo 'Doing something else for something'
Doing something else for something
+ IFS=$'\r'
+ read -r line
+ [[ -z prompt ]]
+ IFS=' '
+ read -a fields
+ command=prompt
+ echo 'PROCESSING prompt'
PROCESSING prompt
+ [[ prompt = prompt ]]
+ read -p 'Please enter a value: ' aValue
+ echo
+ IFS=$'\r'
+ read -r line
+ [[ -n '' ]]
Exemplo de arquivo tsv:
$ cat promptTest.tsv
something else
prompt
otherthing nelse
A maneira mais simples é usar
/dev/tty
como leitura para entrada do teclado.Por exemplo:
Isso quebra se você não executar isso em um terminal e não permitir que a entrada seja redirecionada para o programa, mas funciona muito bem.
De maneira mais geral, você pode pegar um novo identificador de arquivo baseado no stdin original e ler a partir disso. Observe a
exec
linha e oread
Em ambos os casos, o programa se parece um pouco com:
A segunda variação permite que a entrada também seja redirecionada
Este SO Q&A intitulado: Como ler um arquivo ou stdin no Bash? mostra este método que destaca como fazer o que parece que você está procurando:
Você pode duplicar a entrada padrão antes de fazer o redirecionamento.