Em scripts Bash, a interação com o usuário é fundamental para criar ferramentas dinâmicas e adaptáveis. O comando read é a principal forma de capturar entrada do teclado, permitindo que o script reaja a dados fornecidos em tempo de execução. Nesta aula, exploraremos desde o uso básico até técnicas avançadas como prompts personalizados, leitura de múltiplos valores e integração com loops para processamento contínuo.

Dominar read é essencial para criar scripts que solicitam confirmações, coletam parâmetros ou implementam menus interativos. Veremos cada variação com exemplos práticos e boas práticas para evitar armadilhas comuns.

read

O comando read lê uma linha da entrada padrão (geralmente o teclado) e armazena o conteúdo em uma ou mais variáveis. Por padrão, ele lê até encontrar uma quebra de linha (Enter) e divide a linha em palavras usando os caracteres do IFS (Internal Field Separator), que por padrão são espaço, tabulação e nova linha.

Sintaxe básica: read nome_variavel. Se nenhuma variável for fornecida, o conteúdo é armazenado na variável especial REPLY. Exemplo simples:

#!/bin/bash
echo "Digite seu nome:"
read nome
echo "Olá, $nome!"

Quando o script executa, ele aguarda o usuário digitar algo e pressionar Enter. O texto digitado é atribuído à variável nome. É importante notar que read preserva espaços internos se a linha não for dividida por IFS, mas para linhas completas sem divisão, use read -r para evitar interpretação de barras invertidas.

Prompt (-p)

A opção -p permite exibir um prompt diretamente, eliminando a necessidade de um echo separado. O texto do prompt é exibido antes da leitura, e o cursor aguarda a entrada na mesma linha (a menos que o prompt inclua uma quebra de linha). Exemplo:

read -p "Digite sua idade: " idade
echo "Você tem $idade anos."

O prompt é exibido exatamente como fornecido. Para incluir uma nova linha, use \n dentro de aspas duplas (com echo -e ou diretamente no prompt com $'...'). Exemplo com várias linhas:

read -p $'Digite seu nome:\n> ' nome
echo "Nome: $nome"

Isso exibe "Digite seu nome:" em uma linha e "> " na próxima, aguardando a entrada. O uso de -p torna o código mais conciso e legível.

Múltiplas variáveis

O comando read pode atribuir palavras a múltiplas variáveis em uma única chamada. A linha de entrada é dividida de acordo com o IFS, e cada palavra é atribuída às variáveis na ordem. Se houver mais palavras que variáveis, o excedente vai para a última variável. Se houver menos, as variáveis restantes ficam vazias.

read -p "Digite seu nome, idade e cidade: " nome idade cidade
echo "Nome: $nome"
echo "Idade: $idade"
echo "Cidade: $cidade"

Se o usuário digitar "João 30 São Paulo", as variáveis recebem os valores corretos. Se digitar "Maria 25", cidade fica vazia. Se digitar "Pedro 40 Rio de Janeiro", cidade recebe "Rio de Janeiro" (o restante). Para capturar a linha inteira em uma variável, use apenas uma variável ou utilize IFS= para desabilitar a divisão.

Exemplo com IFS personalizado (por exemplo, lendo dados separados por vírgula):

IFS=',' read -p "Digite nome,idade: " nome idade
echo "Nome: $nome, Idade: $idade"

Isso permite processar entradas formatadas de forma flexível.

read em loop

Combinar read com loops é uma técnica poderosa para processar múltiplas entradas ou criar menus interativos. O padrão mais comum é usar while read para ler linhas de um arquivo ou da entrada padrão até EOF. Exemplo lendo de um arquivo:

while read linha; do
  echo "Linha: $linha"
done < arquivo.txt

Para um loop interativo que pergunta repetidamente até que o usuário forneça uma resposta específica:

#!/bin/bash
while true; do
  read -p "Deseja continuar? (s/n): " resposta
  if [[ "$resposta" == "s" ]]; then
    echo "Continuando..."
    # faça algo
  elif [[ "$resposta" == "n" ]]; then
    echo "Saindo."
    break
  else
    echo "Resposta inválida. Digite s ou n."
  fi
done

Outra variação é usar for com uma lista de prompts, mas o while com read é mais flexível para entradas variáveis. Cuidado com loops infinitos: sempre forneça uma condição de saída.

Exemplo de menu com case:

#!/bin/bash
while true; do
  echo "Menu:"
  echo "1. Opção 1"
  echo "2. Opção 2"
  echo "3. Sair"
  read -p "Escolha: " opcao
  case $opcao in
    1) echo "Você escolheu opção 1" ;;
    2) echo "Você escolheu opção 2" ;;
    3) echo "Saindo..."; break ;;
    *) echo "Opção inválida" ;;
  esac
done

Boas práticas

  • Sempre use -r com read para evitar que barras invertidas sejam interpretadas como escapes, a menos que você queira esse comportamento.
  • Valide a entrada do usuário sempre que possível (por exemplo, verificar se é um número).
  • Para senhas, use read -s para não exibir o que é digitado.
  • Limpe o buffer de entrada se necessário (por exemplo, após um loop com leitura mista).
  • Use IFS= read -r para ler linhas exatas sem divisão nem interpretação.

Referências

Exercícios

  1. Escreva um script que pergunte o nome do usuário e exiba uma saudação personalizada. Use read -p.

    ✓ Resposta:
    #!/bin/bash
    read -p "Digite seu nome: " nome
    echo "Olá, $nome! Seja bem-vindo(a)."
  2. Crie um script que leia três números (separados por espaço) e calcule a soma. Use múltiplas variáveis.

    ✓ Resposta:
    #!/bin/bash
    read -p "Digite três números separados por espaço: " a b c
    soma=$((a + b + c))
    echo "A soma é $soma"
  3. Escreva um script que leia linhas de um arquivo (fornecido como argumento) e exiba cada linha numerada. Use while read.

    ✓ Resposta:
    #!/bin/bash
    if [[ -f "$1" ]]; then
      contador=1
      while IFS= read -r linha; do
        echo "$contador: $linha"
        ((contador++))
      done < "$1"
    else
      echo "Arquivo não encontrado."
    fi
  4. Crie um script de menu que apresente as opções: 1 - Data, 2 - Hora, 3 - Sair. Use read em loop com case.

    ✓ Resposta:
    #!/bin/bash
    while true; do
      echo ""
      echo "Menu:"
      echo "1 - Exibir data atual"
      echo "2 - Exibir hora atual"
      echo "3 - Sair"
      read -p "Escolha uma opção: " opcao
      case $opcao in
        1) echo "Data: $(date +%d/%m/%Y)" ;;
        2) echo "Hora: $(date +%H:%M:%S)" ;;
        3) echo "Saindo..."; break ;;
        *) echo "Opção inválida. Tente novamente." ;;
      esac
    done
  5. Faça um script que peça ao usuário para digitar uma senha (sem eco) e confirme a senha em seguida. Se forem iguais, exiba "Senha confirmada", senão "Senhas não conferem". Use read -s.

    ✓ Resposta:
    #!/bin/bash
    read -sp "Digite a senha: " senha1
    echo ""
    read -sp "Confirme a senha: " senha2
    echo ""
    if [[ "$senha1" == "$senha2" ]]; then
      echo "Senha confirmada."
    else
      echo "Senhas não conferem."
    fi