I Bash kan to heltall sammenlignes ved bruk av betinget uttrykk
arg1 OP arg2
OP er en av
-eq
,-ne
,-lt
,-le
,-gt
, eller-ge
. Disse aritmetiske binære operatorene returnerer sant hvis arg1 er lik, ikke lik, mindre enn, mindre enn eller lik, større enn eller større enn eller lik arg2 , henholdsvis. Arg1 og arg2 kan være positive eller negative heltall.
eller aritmetisk uttrykk:
<= >= < >
sammenligning
== !=
likhet og ulikhet
Hvorfor har vi to forskjellige måter å sammenligne to heltall på? Når skal du bruke hvilke?
For eksempel bruker [[ 3 -lt 2 ]]
betinget uttrykk, og (( 3 < 2 ))
bruker aritmetisk uttrykk. Begge returnerer 0 når sammenligningen er sant
Kan disse to metodene alltid brukes om hverandre når man sammenligner to heltall? Hvis ja, hvorfor har Bash to metoder i stedet for en?
Kommentarer
Svar
Ja, vi har to forskjellige måter å sammenligne to heltall på.
Det ser ut til at disse fakta ikke er allment akseptert i dette forumet:
-
Inne i idiomet
[ ]
operatørene for aritmetisk sammenligning er-eq
,-ne
,-lt
,-le
,-gt
og-ge
.Som de også er inne i en testkommando og inne i en
[[ ]]
.Ja inne i disse uttrykkene,
=
,<
osv. Er strengoperatorer. -
Inne i idiomet
(( ))
er operatørene for aritmetisk sammenligning==
,!=
,<
,<=
,>
, og>=
.Nei, dette er ikke en «Aritme etisk utvidelse «(som starter med en
$
) som$(( ))
. Det er definert som en «sammensatt kommando» i man bash.Ja, den følger de samme reglene (internt) for «Aritmetisk utvidelse», men har ingen utgang, bare en utgangsverdi. Det kan brukes slik:
if (( 2 > 1 )); then ...
Hvorfor har vi to forskjellige måter å sammenligne to heltall på?
Jeg antar at sistnevnte (( ))
ble utviklet som en enklere måte å utføre aritmetiske tester på. Det er nesten det samme som $(( ))
, men har bare ingen utdata.
Hvorfor to? Vel det samme som hvorfor vi har to printf
(ekstern og innebygd) eller fire test (ekstern test
, innebygd test
, [
og [[
). Det er slik skjellene vokser, forbedrer noe område på ett år, forbedrer andre neste år.
Når skal du bruke hvilket?
Det er et veldig tøft spørsmål fordi det skal ikke være noen effektiv forskjell. Selvfølgelig er det noen forskjeller i måten et [ ]
arbeid og et (( ))
fungerer internt, men: hva er bedre å sammenligne to heltall? Hvilken som helst !.
Kan disse to metodene alltid brukes om hverandre når man sammenligner to heltall?
For to tall er jeg tvunget til å si ja.
Men for variabler, utvidelser , matematiske operasjoner kan det være viktige forskjeller som bør favorisere den ene eller den andre. Jeg kan ikke si at absolutt begge er like. For det første kan (( ))
utføre flere matteoperasjoner i rekkefølge:
if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi
Hvis ja, hvorfor har Bash to metoder i stedet for en?
Hvis begge er nyttige, hvorfor ikke?
Kommentarer
-
=
er en oppgave og==
er en sammenligning i aritmetiske utvidelser. Spørsmålet siterer det riktig. Men svaret er feil. - Også
(
er ikke et reservert ord i bash, så det er ikke nødvendig å sette mellomrom rundt((
, som i motsetning til[
eller[[
Svar
Historisk eksisterte test
-kommandoen først (i det minste så langt tilbake til Unix Seventh Edition i 1979). Den brukte operatørene =
og !=
for å sammenligne strenger, og -eq
, -ne
, -lt
, etc. for å sammenligne tall. For eksempel er test 0 = 00
usant, men test 0 -eq 00
er sant. Jeg vet ikke hvorfor denne syntaksen ble valgt, men det kan ha vært å unngå å bruke <
og >
, som skallet ville ha analysert som omdirigeringsoperatorer. test
-kommandoen fikk en ny syntaks noen år senere: [ … ]
tilsvarer test …
.
[[ … ]]
betinget syntaks, der <
og >
kan brukes som operatorer uten å sitere, ble lagt til senere, i ksh. Det holdt bakoverkompatibilitet med [ … ]
, så det brukte de samme operatorene, men la til <
og >
for å sammenligne strenger (for eksempel [[ 9 > 10 ]]
men [[ 9 -lt 10 ]]
). For mer informasjon, se ved bruk av enkelt eller dobbelt brakett – bash
Aritmetiske uttrykk kom også senere enn test
kommando,
i Korn-skallet , på et eller annet tidspunkt på 1980-tallet. De fulgte syntaksen til C-språket, som var veldig populært i Unix-kretser. Dermed brukte de C «s-operatorer:==
for likhet,<=
for mindre eller lik osv.
Unix Seventh Edition hadde ikke aritmetiske uttrykk, men den hadde expr
kommandoen , som også implementerte en C-lignende syntaks for heltalloperasjoner, inkludert sammenligningsoperatører. I et skallskript måtte tegnene <
og >
siteres for å beskytte dem mot skallet, f.eks. if expr 1 \< 2; …
tilsvarer if test 1 -lt 2; …
. Tillegg av aritmetiske uttrykk til skallet gjorde mest bruk av expr
foreldet, så det er ikke kjent i dag.
I et sh-skript, du » d bruker vanligvis aritmetiske uttrykk for å beregne et heltall, og [ … ]
for å sammenligne heltall.
if [ "$((x + y))" -lt "$z" ]; then …
I en ksh , bash eller zsh-skript, kan du bruke ((…))
for begge.
if ((x + y < z)); then …
[[ … ]]
-form er nyttig hvis du vil bruke betingede forhold som involverer ting annet enn heltall.
Svar
I henhold til testman-siden, = og! = brukes til strengesammenligning mens uttrykkene -eq, -gt, -lt, -ge, -le og -ne er sammenligninger med heltall. Jeg har alltid fulgt denne konvensjonen når jeg skriver shell-skript, og det fungerer alltid. Vær oppmerksom på at hvis du har variabler i uttrykket, kan det hende du må sitere variablene på en eller annen måte for å unngå å gjøre en null-sammenligning.
På papir gjør vi sammenligninger av streng / tall uten mye tanke. En datamaskin derimot vet ikke om 987 er et tall eller en streng med tegn. Du trenger de forskjellige operatørene for å fortelle datamaskinen hva du skal gjøre, slik at du får riktig resultat. Det er litt tilleggsinformasjon her som forklarer noe av historien. I det vesentlige er variablene utypet og har holdt seg slik for historisk kompatibilitet.
Kommentarer
- I mitt innlegg,
=
og!=
er aritmetiske operatorer, mens siden tiltest
bare viser betingede uttrykksoperatorer.
= != < <= > >=
sammenlign strenger .1 -eq 01
men1 != 01
og8 -lt 42
men8 > 42