KSH - if / then / else vs. amps duplos (&&) e tubos duplos (||)

6

Eu estou querendo saber quais são as melhores práticas em relação a if / then / else; Eu costumo usar o seguinte formulário (porque eu acho mais fácil de ler)

#!/usr/bin/ksh
#

[[ -f /path/to/target/file ]] && {
    echo "File exists"
} || {
    echo "No such file"
}

em vez deste formulário

#!/usr/bin/ksh
#

if [ -f /path/to/target/file ] ; then
    echo "File exists"
else
    echo "No such file"
fi

Eu também incluo uma declaração true antes de } || { para o bloco complexo, para garantir que a parte "else" não seja executada.

Quais são suas recomendações?

    
por Cicatrice 07.04.2015 / 17:31

3 respostas

8

O problema com esse estilo é que os dois formulários não são equivalentes. Quando você usa:

if command; then
    foo
else
    bar
fi

então foo ou bar serão chamados, nunca os dois. Ao usar os dois && e || , ambos os caminhos podem ser obtidos:

$ [[ -d / ]] && {
> echo "Path 1 taken"
> false
> } || {
> echo "Path 2 taken"
> }
Path 1 taken
Path 2 taken
$

Ao usar o formulário if cmd; then foo; else bar; fi , a condição para o bar que está sendo chamado é cmd retornando false. Ao usar o formulário cmd && foo || bar , a condição para o bar que está sendo chamado é cmd && foo retornando false.

EDIT: Eu só notei que na sua pergunta você reconhece que você precisa colocar true no final dos blocos para fazer sua versão funcionar em tudo. Se você está disposto a fazer isso, eu não estou ciente de quaisquer outras questões importantes - mas eu diria que um estilo que requer que você adicione incondicionalmente "verdadeiro" como o último comando em um bloco, se houver alguma possibilidade de que o comando anterior pode falhar apenas garante que você acabará esquecendo, e as coisas vão parecer que estão funcionando corretamente até que eles não o façam.

    
por 07.04.2015 / 18:28
3

Na minha opinião, se-então-else é mais fácil de ler para alguém que escreve em qualquer outro idioma.
Mas minha recomendação seria usar a notação curta (com & & ou ||) somente para one-liners com apenas um dos && e || .
Algum código como

[[ -d mustExist ]] || errorFunction "Dir mustExist is missing"
[[ -f toBeSend ]] && sendFile toBeSend
if [[ -d sometimes ]]; then
   writeTrueBlock
else
   writeFalseBlock
fi

EDIT: Novo pensamento: pode ser ainda melhor escrever isso como

test -d mustExist || errorFunction "Dir mustExist is missing"
test -f toBeSend && sendFile toBeSend
if [[ -d sometimes ]]; then
   writeTrueBlock
else
   writeFalseBlock
fi
    
por 07.04.2015 / 23:43
2

Legibilidade e estilo

Eu costumo usar bastante os operadores && e || em meus scripts.

Eu até uso mais de um em uma única instrução, mas apenas em seções que verificam se continuam no bloco atual.

Exemplo1:

for word in $list; do
    condition1 $word || continue
    condition2 $word || continue

    : do stuff with $word
    : do more stuff with $word
done

condição1 e condição2 atuam como asserções. Nós temos as exceções fora do caminho , e continue com o que este pedaço de código é deveria fazer.

Usar if ... then ... fi nesse caso seria um pouco estranho.

Notações alternativas:

Exemplo2:

for word in $list; do
    if condition1 $word && condition2 $word; then
        : do stuff with $word
        : do more stuff with $word
    fi
done

Em exemplo2 , temos outro nível de recuo, enquanto nada extra está acontecendo.

Exemplo3:

for word in $list; do
    condition1 $word && condition2 $word || continue
    : do stuff with $word
    : do more stuff with $word
done

Se as duas condições podem ser expressas simplesmente, às vezes eu combino -los como no Example3.

P.S: Eu originalmente adicionei um Exercício para o programador de shell: Apenas dois dos três exemplos são totalmente equivalentes. Qual é o estranho fora? Acontece que a diferença que eu pensava haver não estava lá. Na verdade, eu escrevi um teste shpec :

describe "continue"
  it "discards last exit status"
    (for i in 1; do
     false || continue
     done
    )
    assert equal 0 $?
  end
end

shpec/continue_shpec.sh
continue
  discards last exit status
  1 examples, 0 failures
    
por 08.04.2015 / 21:23