Podczas pisania skryptów zazwyczaj piszę ifs z następującą składnią, ponieważ łatwiej mi zrozumieć, że to, co nastąpi później, nie jest prawdą.
if [ ! "$1" = "$2" ]; then
Inni twierdzą, że sposób poniżej jest lepszy
if [ "$1" != "$2" ]; then
Chodzi o to, kiedy pytam, dlaczego i czy są jakieś różnice, nikt nie wydaje się mieć żadnej odpowiedzi.
Czy są jakieś różnice między tymi dwiema składniami? Czy jeden z nich jest bezpieczniejszy od drugiego? Czy to tylko kwestia preferencji / nawyku?
!(x==y)
od(!x)==y
.if [ ! "$string" = "one" ]
przekłada się to na, jeśli nie, wartość$string
równąone
. A toif [ "$string" != "one"]
przekłada się na to, czy wartość$string
nie jest równaone
?!=
składnia) jest po prostu bardziej oczywiste.Odpowiedzi:
Oprócz argumentów kosmetycznych / preferencji, jednym z powodów może być to, że jest więcej implementacji, w których
[ ! "$a" = "$b" ]
zawodzi się w przypadkach narożnych niż z[ "$a" != "$b" ]
.Oba przypadki powinny być bezpieczne, jeśli implementacje są zgodne z algorytmem POSIX , ale nawet dzisiaj (na początku 2018 r. W momencie pisania) nadal istnieją implementacje, które zawodzą. Na przykład z
a='(' b=')'
:Na przykład w
dash
wersjach wcześniejszych niż 0.5.9, takich jak 0.5.8, jaksh
na przykład Ubuntu 16.04:(naprawiony w wersji 0.5.9, patrz https://www.mail-archive.com/[email protected]/msg00911.html )
Te implementacje traktują
[ ! "(" = ")" ]
tak[ ! "(" "text" ")" ]
, jak jest[ ! "text" ]
(sprawdź, czy „tekst” jest łańcuchem pustym), podczas gdy POSIX tak nakazuje[ ! "x" = "y" ]
(przetestuj „x” i „y” pod kątem równości). Te implementacje kończą się niepowodzeniem, ponieważ w tym przypadku wykonują zły test.Pamiętaj, że istnieje jeszcze jedna forma:
Ten wymaga powłoki POSIX (nie będzie działać ze starą powłoką Bourne'a).
Zauważ, że kilka implementacji miało również problemy z
[ "$a" = "$b" ]
(i[ "$a" != "$b" ]
) i nadal działa podobnie jak[
wbudowane/bin/sh
w Solaris 10 (powłoka Bourne'a, w której znajduje się powłoka POSIX/usr/xpg4/bin/sh
). Dlatego widzisz takie rzeczy jak:W skryptach próbuje być przenośny na stare systemy.
źródło
! "$a" = "b"
musisz być bardziej ostrożny przy pisaniu, aby określić porównanie. Z twojego przykładu rozumiem, że drugie polecenie powraca,not zero
co może być zarówno korzystne, jak i kłopotliwe. Może być korzystne, jeśli chcesz wyjść, jeśli się nie zgadzają, lub niepokojące, jeśli chcesz zobaczyć, czy porównanie się[ ! "$a" = "$b" ]
po prostu się nie udaje, kiedy$a
jest(
i$b
jest)
, twierdzi, że są identyczne, gdy nie są, nie(
jest taki sam jak)
, ale[
w tym przypadku wykonuje zły test.[ ! "$a" = "$b" ]
czasami jest niepoprawnie traktowane w błędnych implementacjach powłoki (co moim zdaniem jest mniej więcej powtórzeniem pierwszego zdania odpowiedzi).x != y
Składnia jest lepiej, bo! x == y
jest podatny na błędy - wymaga wiedzy operatorów pierwszeństwa, które różni się od języka na język. Składnia! x == y
może być interpretowany jako!(x == y)
lub(!x) == y
, w zależności od priorytetu!
vs=
.Na przykład
c++
negacja!
występuje przed operatorem porównania / relacji==
, stąd następujący kod:zwraca
Podobne zachowanie można zaobserwować w wielu innych językach, w tym np.
awk
- często używanym narzędziu w świecie uniksowym.Z drugiej strony, gromadzenie operatorów razem poprzez
x != y
nie prowadzi do zamieszania jako dobrze ugruntowanego wzorca. Co więcej, technicznie rzecz biorąc!=
bardzo często nie jest to dwa, ale tylko jeden operator, więc powinno być nawet marginalnie szybsze do oceny niż oddzielne porównanie, a następnie negacja. Dlatego, mimo że obie składnie działają w trybie bash, zalecam ich przestrzeganie,x != y
ponieważ łatwiej jest czytać i utrzymywać kod zgodny ze standardową logiką.źródło
Tego rodzaju rzeczy są bardzo oparte na opiniach, ponieważ „odpowiedź” zależy bardzo silnie od sposobu, w jaki mózg jednostki jest okablowany. Chociaż prawdą jest, że semantycznie
NOT ( A == B )
jest identyczny(A != B )
, jeden może być bardziej zrozumiały dla jednej osoby, a drugi dla drugiej. Jest również zależny od kontekstu. Na przykład, jeśli mam ustawioną flagę, znaczenia mogą być wyraźniejsze przy jednej składni nad drugą:w przeciwieństwie do
źródło
if ( FS_OPEN != fileHandleStatus )
w wyniku łatwości przypadkowego pisania=
zamiast==
w językach, w których pierwszym jest przypisanie, a później test równości (jak C) ...