Lors de l'écriture de scripts, j'écris généralement mes ifs avec la syntaxe suivante car il est plus facile pour moi de comprendre que ce qui vient ensuite n'est pas vrai.
if [ ! "$1" = "$2" ]; then
D'autres disent que le chemin ci-dessous est meilleur
if [ "$1" != "$2" ]; then
Le problème, c'est quand je demande pourquoi et s'il y a des différences, personne ne semble avoir de réponse.
Alors, y a-t-il des différences entre les deux syntaxes? L'un est-il plus sûr que l'autre? Ou s'agit-il simplement d'une question de préférence / d'habitude?
!(x==y)
de(!x)==y
.if [ ! "$string" = "one" ]
traduit par sinon la valeur de$string
égalone
. Et cela seif [ "$string" != "one"]
traduit par si la valeur de$string
n'est pas égale àone
?!=
syntaxe) est juste plus évident.Réponses:
Outre les arguments cosmétiques / préférence, une des raisons pourrait être qu'il y a plus d'implémentations où
[ ! "$a" = "$b" ]
échoue dans les cas d'angle qu'avec[ "$a" != "$b" ]
.Les deux cas devraient être sûrs si les implémentations suivent l'algorithme POSIX , mais même aujourd'hui (début 2018 au moment de l'écriture), il y a toujours des implémentations qui échouent. Par exemple, avec
a='(' b=')'
:Avec les
dash
versions antérieures à 0.5.9, comme la 0.5.8 trouvéesh
sur Ubuntu 16.04 par exemple:(corrigé dans 0.5.9, voir https://www.mail-archive.com/[email protected]/msg00911.html )
Ces implémentations traitent
[ ! "(" = ")" ]
comme[ ! "(" "text" ")" ]
c'est[ ! "text" ]
(test si « texte » est la chaîne null) alors que les mandats POSIX à être[ ! "x" = "y" ]
(test « x » et « y » pour l' égalité). Ces implémentations échouent car elles effectuent le mauvais test dans ce cas.Notez qu'il existe encore un autre formulaire:
Celui-ci nécessite un shell POSIX (ne fonctionnera pas avec l'ancien shell Bourne).
Notez que plusieurs implémentations ont également eu des problèmes avec
[ "$a" = "$b" ]
(et[ "$a" != "$b" ]
) et font toujours comme le[
buildin de/bin/sh
Solaris 10 (un shell Bourne, le shell POSIX étant dedans/usr/xpg4/bin/sh
). Voilà pourquoi vous voyez des choses comme:Dans des scripts essayant d'être portables sur d'anciens systèmes.
la source
! "$a" = "b"
vous devez être plus prudent sur la façon dont vous l'écrivez pour spécifier la comparaison. D'après votre exemple, je comprends que la deuxième commande revient,not zero
ce qui pourrait être à la fois bénéfique ou troublant. Cela pourrait être bénéfique si vous voulez quitter si elles ne correspondent pas, ou troublant si vous voulez voir si la comparaison s'est écrasée[ ! "$a" = "$b" ]
échouent simplement quand$a
est(
et$b
est)
, il prétend qu'elles sont identiques quand elles ne le sont pas,(
n'est pas la même chaîne que)
, mais[
effectue le mauvais test dans ce cas.[ ! "$a" = "$b" ]
est parfois géré de manière incorrecte dans les implémentations de shell buggy (ce qui, je pense, reprend plus ou moins la première phrase de la réponse).La
x != y
syntaxe est meilleure car elle! x == y
est sujette aux erreurs - nécessite une connaissance de la priorité des opérateurs qui diffère d'une langue à l'autre. La syntaxe! x == y
pourrait être interprétée comme!(x == y)
ou(!x) == y
, en fonction de la priorité de!
vs=
.Par exemple, la
c++
négation!
précède l'opérateur de comparaison / relationnel==
, d'où le code suivant:résultats
Un comportement similaire peut être observé dans de nombreuses autres langues, y compris par exemple
awk
- un outil fréquemment utilisé dans le monde Unix.En revanche, le regroupement des opérateurs via
x != y
ne conduit à aucune confusion en tant que modèle bien établi. De plus, techniquement parlant, il!=
s'agit très souvent non pas de deux, mais d'un seul opérateur, ce qui devrait être encore légèrement plus rapide à évaluer qu'une comparaison séparée puis une négation. Par conséquent, bien que les deux syntaxes fonctionnent en bash, je recommanderais de suivrex != y
car il est beaucoup plus facile de lire et de maintenir du code qui suit une logique standard.la source
Ce genre de chose est très basé sur l'opinion, car la "réponse" dépend très fortement de la façon dont le cerveau d'un individu est câblé. S'il est vrai que sémantiquement,
NOT ( A == B )
est identique à(A != B )
, l'un pourrait être plus clair pour une personne et l'autre pour une autre. Il dépend également du contexte. Par exemple, si j'ai un indicateur défini, les significations pourraient être plus claires avec une syntaxe par rapport à une autre:par opposition à
la source
if ( FS_OPEN != fileHandleStatus )
en raison de la facilité de taper accidentellement=
plutôt que==
dans les langues où le premier est assigné et le test d'égalité ultérieur (comme C) ...