Abuse o operador ternário ((test)) && cmd1 || cmd2
ou [ test ] && cmd1 || cmd2
, tanto quanto possível.
Exemplos (contagens de comprimento sempre excluem a linha superior):
t="$something"
if [ $t == "hi" ];then
cmd1
cmd2
elif [ $t == "bye" ];then
cmd3
cmd4
else
cmd5
if [ $t == "sup" ];then
cmd6
fi
fi
Usando apenas operadores ternários, isso pode ser facilmente reduzido para:
t="$something"
[ $t == "hi" ]&&{
cmd1;cmd2
}||[ $t == "bye" ]&&{
cmd3;cmd4
}||{
cmd5
[ $t == "sup" ]&&cmd6
}
Como nyuszika7h apontou nos comentários, este exemplo específico pode ser reduzido ainda mais usando case
:
t="$something"
case $t in "hi")cmd1;cmd2;;"bye")cmd3;cmd4;;*)cmd5;[ $t == "sup" ]&&cmd6;esac
Além disso, prefira parênteses a chaves, tanto quanto possível. Como os parênteses são um metacaractere, e não uma palavra, eles nunca requerem espaços em nenhum contexto. Isso também significa executar o maior número possível de comandos em um subshell, porque chaves entre chaves (ie {
e }
) são palavras reservadas, não meta caracteres, e, portanto, precisam ter espaço em branco em ambos os lados para analisar corretamente, mas as meta caracteres não. Suponho que você já saiba que os subshells não afetam o ambiente pai; portanto, supondo que todos os comandos de exemplo possam ser executados com segurança em um subshell (o que não é típico em nenhum caso), você pode encurtar o código acima para isso :
t=$something
[ $t == "hi" ]&&(cmd1;cmd2)||[ $t == "bye" ]&&(cmd3;cmd4)||(cmd5;[ $t == "sup" ]&&cmd6)
Além disso, se você não puder, usar parênteses ainda poderá reduzi-lo um pouco. Um aspecto a ter em mente é que ele funciona apenas para números inteiros, o que o torna inútil para os fins deste exemplo (mas é muito melhor do que usar -eq
para números inteiros).
Mais uma coisa, evite aspas sempre que possível. Usando o conselho acima, você pode reduzi-lo ainda mais. Exemplo:
t=$something
[ $t == hi ]&&(cmd1;cmd2)||[ $t == bye ]&&(cmd3;cmd4)||(cmd5;[ $t == sup ]&&cmd6)
Nas condições de teste, prefira colchetes simples a duplos, tanto quanto possível, com algumas exceções. Ele solta dois caracteres de graça, mas em alguns casos não é tão robusto (é uma extensão do Bash - veja abaixo um exemplo). Além disso, use o argumento igual a um e não o dobro. É um personagem grátis para soltar.
[[ $f == b ]]&&: # ... <-- Bad
[ $f == b ]&&: # ... <-- Better
[ $f = b ]&&: # ... <-- Best. word splits and pathname-expands the contents of $f. Esp. bad if it starts with -
Observe esta ressalva, especialmente na verificação de saída nula ou de uma variável indefinida:
[[ $f ]]&&: # double quotes aren't needed inside [[, which can save chars
[ "$f" = '' ]&&: <-- This is significantly longer
[ -n "$f" ]&&:
Com toda a tecnicidade, este exemplo específico seria melhor com case
... in
:
t=$something
case $t in hi)cmd1;cmd2;;bye)cmd3;cmd4;;*)cmd5;[ $t == sup ]&&cmd6;esac
PS: Aqui está uma lista de meta-caracteres reconhecidos no Bash, independentemente do contexto (e podem separar palavras):
EDIT: Como apontou manatwork, o teste de parênteses duplos funciona apenas para números inteiros. Além disso, indiretamente, descobri que você precisa ter um espaço em branco ao redor do ==
operador. Corrigido minha postagem acima.
Eu também estava com preguiça de recalcular o comprimento de cada segmento, então simplesmente os removi. Deve ser fácil encontrar uma calculadora de comprimento de cordas online, se necessário.
sh
e qual shell permite essafor
sintaxe? é expressamente permitido entrarzsh
.