W Bash dwie liczby całkowite można porównać za pomocą wyrażenia warunkowego
arg1 OP arg2
PO jest jednym
-eq
,-ne
,-lt
,-le
,-gt
, i-ge
. Te arytmetyczne operatory binarne zwracają wartość true, jeśli arg1 jest odpowiednio równy, nie równy, mniejszy, mniejszy lub równy, większy niż lub większy niż lub równy arg2 . Arg1 i arg2 mogą być dodatnimi lub ujemnymi liczbami całkowitymi.
lub wyrażenie arytmetyczne:
<= >= < >
porównanie
== !=
równość i nierówność
Dlaczego mamy dwa różne sposoby porównywania dwóch liczb całkowitych? Kiedy stosować który?
Na przykład [[ 3 -lt 2 ]]
używa wyrażenia warunkowego i (( 3 < 2 ))
używa wyrażenia arytmetycznego. Oba zwracają 0, gdy porównanie jest prawdziwe
Czy porównując dwie liczby całkowite, zawsze można stosować te dwie metody zamiennie? Jeśli tak, to dlaczego Bash ma dwie metody zamiast jednej?
= != < <= > >=
porównaj ciągi .1 -eq 01
ale1 != 01
i8 -lt 42
ale8 > 42
Odpowiedzi:
Tak, mamy dwa różne sposoby porównywania dwóch liczb całkowitych.
Wygląda na to, że te fakty nie są powszechnie akceptowane na tym forum:
Wewnątrz idiomu
[ ]
operatory dla arytmetyki porównań-eq
,-ne
,-lt
,-le
,-gt
i-ge
.Ponieważ są one również wewnątrz polecenia testowego i wewnątrz
[[ ]]
.Tak Wewnątrz idiomów,
=
,<
, itd. Są operatory łańcuchowe.Wewnątrz idiomu
(( ))
operatory dla arytmetyki porównań==
,!=
,<
,<=
,>
, i>=
.Nie, nie jest to „rozszerzenie arytmetyczne” (zaczynające się od a
$
) as$(( ))
. Jest zdefiniowany jako „Polecenie złożone” w man bash.Tak, zgodnie z tymi samymi zasadami (wewnętrznie), co „rozszerzenie arytmetyczne”, nie ma danych wyjściowych, a jedynie wartość wyjściową. Można go użyć w następujący sposób:
Dlaczego mamy dwa różne sposoby porównywania dwóch liczb całkowitych?
Myślę, że ten ostatni
(( ))
został opracowany jako prostszy sposób wykonywania testów arytmetycznych. Jest prawie taki sam jak ten,$(( ))
ale po prostu nie ma wyjścia.Dlaczego dwa? Cóż, to samo, dlaczego mamy dwa
printf
(zewnętrzne i wbudowane) lub cztery testy (zewnętrznetest
, wbudowanetest
,[
i[[
). W ten sposób rosną muszle, poprawiając niektóre obszary w ciągu jednego roku, poprawiając inne w następnym roku.Kiedy stosować który?
To bardzo trudne pytanie, ponieważ nie powinno być skutecznej różnicy. Oczywiście istnieją pewne różnice w sposobie
[ ]
pracy i(( ))
pracy wewnętrznej, ale: co lepiej porównać dwie liczby całkowite? Każdy!Czy porównując dwie liczby całkowite, zawsze można stosować te dwie metody zamiennie?
W przypadku dwóch liczb jestem zmuszony powiedzieć tak.
Ale w przypadku zmiennych, rozszerzeń, operacji matematycznych mogą występować kluczowe różnice, które powinny sprzyjać jednemu lub drugiemu. Nie mogę powiedzieć, że absolutnie oba są równe. Po pierwsze,
(( ))
mogą wykonywać kolejno kilka operacji matematycznych:Jeśli tak, to dlaczego Bash ma dwie metody zamiast jednej?
Jeśli oba są pomocne, dlaczego nie?
źródło
=
jest zadaniem i==
stanowi porównanie rozszerzeń arytmetycznych. Pytanie cytuje to poprawnie. Ale odpowiedź jest zła.Historycznie
test
komenda istniała jako pierwsza (przynajmniej jeszcze w 7. edycji Unix w siódmej edycji ). Stosowany operatorów=
i!=
porównać strun, i-eq
,-ne
,-lt
, itd., Aby porównać numery. Na przykładtest 0 = 00
jest fałszywy, aletest 0 -eq 00
jest prawdziwy. Nie wiem, dlaczego wybrano tę składnię, ale być może trzeba było unikać używania<
i>
, które powłoka analizowałaby jako operatory przekierowania.test
Polecenie dostał inną składnię kilka lat później:[ … ]
jest równoważnatest …
.[[ … ]]
Składni warunkowe, wewnątrz której<
i>
może być stosowany jako podmiotów bez podania dodano później, w KSH. Zachował kompatybilność wsteczną[ … ]
, więc używał tych samych operatorów, ale dodawał<
i>
porównywał ciągi znaków (na przykład,[[ 9 > 10 ]]
ale[[ 9 -lt 10 ]]
). Aby uzyskać więcej informacji, zobacz używanie pojedynczego lub podwójnego nawiasu klamrowegoWyrażenia arytmetyczne pojawiły się później niż
test
polecenie, w powłoce Korna , w pewnym momencie w latach 80. Postępowali zgodnie ze składnią języka C, który był bardzo popularny w kręgach uniksowych. Dlatego używali operatorów C:==
dla równości,<=
dla mniejszej lub równej itp.Unix Siódma Edycja nie miała wyrażeń arytmetycznych, ale miała
expr
komendę , która również implementowała składnię podobną do C dla operacji na liczbach całkowitych, w tym operatorów porównania. W skrypcie powłoki znaki<
i znaki>
muszą być cytowane, aby chronić je przed powłoką, np.if expr 1 \< 2; …
Jest równoważneif test 1 -lt 2; …
. Dodanie wyrażeń arytmetycznych do powłoki spowodowało, że większość zastosowań byłaexpr
przestarzała, więc nie jest ona dziś dobrze znana.W skrypcie sh zwykle używasz wyrażeń arytmetycznych do obliczania wartości liczb całkowitych i
[ … ]
do porównywania liczb całkowitych.W skrypcie ksh, bash lub zsh możesz używać
((…))
obu.[[ … ]]
Forma jest przydatna, jeśli chcesz skorzystać z udziałem warunkowe rzeczy inne niż liczb całkowitych.źródło
Według strony podręcznika testowego do porównań łańcuchów używane są = i! =, Natomiast wyrażenia -eq, -gt, -lt, -ge, -le i -ne są porównaniami liczb całkowitych. Zawsze przestrzegałem tej konwencji podczas pisania skryptów powłoki i zawsze działa. Należy pamiętać, że jeśli masz zmienne w wyrażeniu, może być konieczne zacytowanie zmiennych w jakiś sposób, aby uniknąć porównania zerowego.
Na papierze dokonujemy porównań ciągów / liczb bez namysłu. Z drugiej strony komputer nie wie, czy 987 jest liczbą, czy ciągiem znaków. Potrzebujesz różnych operatorów, którzy powiedzą komputerowi, co zrobić, aby uzyskać właściwy wynik. Jest tu kilka dodatkowych informacji , które wyjaśniają część historii. Zasadniczo zmienne są nietypowe i pozostały w ten sposób dla historycznej zgodności.
źródło
=
i!=
są operatory arytmetyczne, natomiast podręcznika ztest
tylko pokazuje warunkowe operatory wyrażeń.