A sintaxe de não é igual é importante?

21

Quando escrevo, costumo escrever meus ifs com a seguinte sintaxe, pois é mais fácil para mim entender que o que vem a seguir não é verdade.

if [ ! "$1" = "$2" ]; then

Outros dizem que o caminho abaixo é melhor

if [ "$1" != "$2" ]; then

A questão é quando eu pergunto por que e se há alguma diferença que ninguém parece ter nenhuma resposta.

Existem diferenças entre as duas sintaxes? Um deles é mais seguro que o outro? Ou é apenas uma questão de preferência / hábito?

    
por Jimmy_A 12.01.2018 / 17:18

3 respostas

35

Além dos argumentos cosméticos / preferenciais, uma razão pode ser que existam mais implementações nas quais [ ! "$a" = "$b" ] falha em casos de canto do que com [ "$a" != "$b" ] .

Ambos os casos devem ser seguros se as implementações seguirem o algoritmo POSIX , mas mesmo hoje (início de 2018, por escrito), ainda existem implementações que falham. Por exemplo, com a='(' b=')' :

$ (a='(' b=')'; busybox test "$a" != "$b"; echo "$?")
0
$ (a='(' b=')'; busybox test ! "$a" = "$b"; echo "$?")
1

Com dash versões anteriores à 0.5.9, como a 0.5.8 encontrada como sh no Ubuntu 16.04, por exemplo:

$ a='(' b=')' dash -c '[ "$a" != "$b" ]; echo "$?"'
0
$ a='(' b=')' dash -c '[ ! "$a" = "$b" ]; echo "$?"'
1

(corrigido em 0.5.9, consulte link )

Essas implementações tratam [ ! "(" = ")" ] como [ ! "(" "text" ")" ] que é [ ! "text" ] (teste se "texto" é a cadeia nula) enquanto POSIX ordena que seja [ ! "x" = "y" ] (teste "x" e "y" para igualdade) . Essas implementações falham porque executam o teste errado nesse caso.

Note que ainda existe outra forma:

! [ "$a" = "$b" ]

Esse requer um shell POSIX (não funciona com o shell antigo do Bourne).

Observe que várias implementações tiveram problemas com [ "$a" = "$b" ] (e [ "$a" != "$b" ] ) também a> e ainda gosto do [ embutido de /bin/sh no Solaris 10 (um shell Bourne, sendo o shell POSIX em /usr/xpg4/bin/sh ). É por isso que você vê coisas como:

[ "x$a" != "x$b" ]

Em scripts que tentam ser portáteis para sistemas antigos.

    
por 12.01.2018 / 17:32
8

A sintaxe x != y é melhor porque ! x == y é propenso a erros - exige 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, em c++ negation ! vem antes do operador de comparação / relacional == , daí o seguinte código:

#include<iostream>

using namespace std;

int main()
{
  int x=1, y=2;
  if(     x  != y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(  !  x  == y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(  !( x  == y ) ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(   (!x) == y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
}

retorna

true
false
true
false

Comportamento semelhante pode ser observado em muitos outros idiomas, incluindo, e. awk - uma ferramenta usada com freqüência no mundo Unix.

Por outro lado, reunir operadores por meio de x != y não gera confusão como um padrão bem estabelecido. Além disso, tecnicamente falando, != não é muitas vezes dois, mas apenas um operador, portanto, deve ser até mesmo marginalmente mais rápido de avaliar do que a comparação separada e, em seguida, a negação. Portanto, embora ambas as sintaxes funcionem no bash, eu recomendaria seguir x != y , pois é mais fácil ler e manter o código que segue alguma lógica padrão.

    
por 12.01.2018 / 23:37
4

Esse tipo de coisa é muito baseada em opiniões, já que a "resposta" depende muito do modo como o cérebro de um indivíduo é conectado. Embora seja verdade que semanticamente, NOT ( A == B ) é idêntico a (A != B ) , pode ser mais claro para uma pessoa e a outra para outra. Também é dependente do contexto. Por exemplo, se eu tiver um sinalizador definido, os significados podem ser mais claros com uma sintaxe sobre a outra:

if NOT ( fileHandleStatus == FS_OPEN )

ao contrário de

if ( fileHandleStatus != FS_OPEN )
    
por 12.01.2018 / 17:34

Tags