Ao criar scripts, geralmente escrevo meus ifs com a seguinte sintaxe, pois é mais fácil para mim entender que o que vem a seguir não é verdadeiro.
if [ ! "$1" = "$2" ]; then
Outros dizem que o caminho abaixo é melhor
if [ "$1" != "$2" ]; then
O problema é que, quando pergunto por que e se existem diferenças, ninguém parece ter uma resposta.
Então, há alguma diferença entre as duas sintaxes? Um deles é mais seguro que o outro? Ou é apenas uma questão de preferência/hábito?
Além dos argumentos de cosmética/preferência, uma razão pode ser que há mais implementações onde
[ ! "$a" = "$b" ]
falha em casos extremos do que com[ "$a" != "$b" ]
.Ambos os casos devem ser seguros se as implementações seguirem o algoritmo POSIX , mas até hoje (início de 2018 até o momento), ainda existem implementações que falham. Por exemplo, com
a='(' b=')'
:Com
dash
versões anteriores a 0.5.9, como a 0.5.8 encontradash
no Ubuntu 16.04 por exemplo:(corrigido em 0.5.9, consulte https://www.mail-archive.com/[email protected]/msg00911.html )
Essas implementações tratam
[ ! "(" = ")" ]
como[ ! "(" "text" ")" ]
é[ ! "text" ]
(testa se "texto" é a string nula), enquanto o POSIX exige que seja[ ! "x" = "y" ]
(teste "x" e "y" para igualdade). Essas implementações falham porque executam o teste errado nesse caso.Observe que há ainda outro formulário:
Esse requer um shell POSIX (não funcionará com o antigo shell Bourne).
Observe que várias implementações também tiveram problemas com
[ "$a" = "$b" ]
(e[ "$a" != "$b" ]
) e ainda funcionam como o[
built-in do/bin/sh
Solaris 10 (um shell Bourne, o shell POSIX estando em/usr/xpg4/bin/sh
). É por isso que você vê coisas como:Em scripts tentando ser portáveis para sistemas antigos.
A
x != y
sintaxe é melhor porque! x == y
é propensa a erros - requer conhecimento da precedência dos operadores, que difere de idioma para idioma. A sintaxe! x == y
pode ser interpretada como!(x == y)
ou(!x) == y
, dependendo da prioridade de!
vs=
.Por exemplo, na
c++
negação!
vem antes do operador de comparação/relacional==
, daí o seguinte código:retorna
Comportamento semelhante pode ser observado em muitas outras linguagens, incluindo, por exemplo
awk
- uma ferramenta frequentemente usada no mundo Unix.Por outro lado, reunir operadores via
x != y
não gera confusão como um padrão bem estabelecido. Além disso, tecnicamente falando,!=
muitas vezes não são dois, mas apenas um operador, portanto, deve ser ainda mais rápido avaliar do que a comparação separada e a negação. Portanto, embora ambas as sintaxes funcionem no bash, eu recomendaria seguirx != y
, pois é muito mais fácil ler e manter o código que segue alguma lógica padrão.Esse tipo de coisa é muito baseado em opinião, pois a "resposta" depende muito da maneira como o cérebro de um indivíduo está conectado. Embora seja verdade que semanticamente,
NOT ( A == B )
seja idêntico a(A != B )
, um pode ser mais claro para uma pessoa e o outro para outra. Também é dependente do contexto. Por exemplo, se eu tiver um sinalizador definido, os significados podem ser mais claros com uma sintaxe em vez de outra:em oposição a