Como faço para loop uma instrução if no bash?

Quero que o usuário faça uma pergunta e forneça a resposta, que será armazenada em uma variável chamada i, então se a resposta (qual é um arquivo) existe e é gravável, ele o lê e executa greps dentro do arquivo e grava essas coisas em um novo. Se o arquivo não existir ou se o usuário não tiver permissões suficientes sobre o arquivo, um aviso será exibido, o programa ficará suspenso por 3 segundos e os loops serão reiniciados. Por que não está funcionando? O aviso simplesmente não vai embora, nem o loop continuará.

echo "$(tput setaf 4) Tell me where the file is:" printf "\n" a=false while [ $a=true ]; do read i if [ -w $i ] then cat $i | grep stuff > i2 else a=true printf "Oh something is wrong, try again!" sleep 3 fi done 

Resposta

Você tem erros lógicos e de sintaxe.

O $a=true é apenas uma string, NÃO uma operação de comparação. Separe com espaços para que a comparação ocorra: "$a" = true.

Com isso funcionando, o loop não será inserido, conforme você define a=false adiantado.

SE VOCÊ finalmente entrar no loop, não será capaz de sair, pois a nunca é definido para qualquer coisa exceto true, nem outro mecanismo de saída (por exemplo, break) fornecido.

Resposta

Como outros apontaram, você tem erros lógicos e erros de sintaxe em seu código. O site ShellCheck é bom para eliminar os erros de sintaxe.

Esta é minha opinião sobre isso. Tenho duas versões do código . O primeiro (que eu prefiro) não tem interação com o usuário, mas usa um nome de caminho na linha de comando. O segundo pede interativamente um nome de caminho.

A razão de o primeiro não solicitar interativamente um nome do caminho é que faz pouca diferença se o usuário do script escreve o nome do caminho na linha de comando ou no prompt do seu script, e ter o prompt do script para o nome do caminho o desqualifica de ser usado, por exemplo um cron job ou qualquer outro lugar onde não haja um terminal conectado.

#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi 

O echo acima será executado quando

  • o arquivo em $pathname não pode “ser lido, ou
  • o arquivo i2 não pode “ser escrito, ou
  • o padrão não foi encontrado em $pathname (isso é diferente do seu código, mas veja abaixo) .

A mensagem de erro é gravada no erro padrão, como é o costume com mensagens de diagnóstico em geral.

Com prompt interativo e atraso:

#!/bin/bash while true; do read -r -p "Pathname: " pathname if grep "pattern" <$pathname >i2; then break fi echo "Something is wrong" >&2 sleep 3 done 

Aqui, temos um loop infinito que lê do usuário e sai do loop se a chamada grep der certo. Se grep falhar por qualquer motivo (um dos três motivos acima), o nome do caminho será solicitado novamente.


Ambas as partes do código com um teste para um arquivo legível (grep pode falhar por não encontrar nada ou não ser capaz de gravar em seu arquivo de saída.

Primeiro, o não interativo versão:

#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2 

Em seguida, a versão interativa:

#!/bin/bash while true; do read -r -p "Pathname: " pathname if [ -r "$pathname" ]; then grep "pattern" <$pathname >i2 break fi echo "Something is wrong" >&2 sleep 3 done 

Ou uma versão interativa onde o loop lida apenas com a entrada e validação do usuário:

#!/bin/bash while true; do read -r -p "Pathname: " pathname [ -r "$pathname" ] && break echo "Something is wrong" >&2 sleep 3 done grep "pattern" <$pathname >i2 

Resposta

Tente usar simplesmente interromper para interromper o loop infinito como este:

echo "$(tput setaf 4) Tell me where the file is:" echo # This prints empty line like printf "\n" while true; do # "while true" or "while :" is infinite loop read i if [ -r $i ] # You probably mean -r (readable) and not -w (writable) then cat $i | grep stuff > i2 break # "break" ends loop else echo -n "Oh something is wrong, try again!" # "echo -n" means print without newline character sleep 3 fi done 

Lugares modificados têm comentários com descrição.

Comentários

  • grep <$i >i2 em vez de cat. Além disso, cite expansões de variáveis quando necessário, como no teste .

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *