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

1

Eu quero que o usuário seja solicitado com uma pergunta e forneça a resposta, que será armazenada sob uma variável chamada i, e se a resposta (que é um arquivo) existir e for gravável, ela será lida e mostrada dentro do arquivo e escreva essas coisas para um novo. Se o arquivo não existir ou o usuário não tiver permissões suficientes sobre esse arquivo, um aviso será solicitado, o programa ficará inativo por 3 segundos e os loops serão iniciados novamente. 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
    
por Don Jhoe 14.10.2018 / 18:34

3 respostas

2

Você tem sintaxe e erros lógicos.

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

Com isso funcionando, o loop não será inserido, já que você definiu a=false antecipadamente.

DEVEM finalmente entrar no loop, você não poderá sair, já que a nunca está definido para nada além de true , nem outro mecanismo de saída (por exemplo, break ) é fornecido.

    
por 14.10.2018 / 18:55
1

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

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

A razão pela qual o primeiro não interativamente solicita um nome de caminho é que faz pouca diferença se o usuário do script gravar o nome do caminho na linha de comando ou no prompt do seu script, e ter o prompt de script para o nome do caminho desclassificado 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 gravado 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 é costume nas mensagens de diagnóstico em geral.

Com aviso e atraso interativos:

#!/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ê o usuário e sai do loop se a chamada grep foi ok. Se grep falhar por qualquer motivo (uma das três razões acima), o nome do caminho será solicitado novamente.

Ambos os trechos de código com um teste separado para um arquivo legível (o grep tem permissão para falhar por não encontrar nada ou não conseguir gravar em seu arquivo de saída.

Primeiro, a versão não interativa:

#!/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 em que o loop lida apenas com 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
    
por 14.10.2018 / 22:31
0

Tente usar simplesmente interromper para parar o loop infinito da seguinte forma:

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.

    
por 14.10.2018 / 21:24