Jämföra heltal: aritmetiskt uttryck eller villkorligt uttryck

I Bash kan två heltal jämföras med villkorligt uttryck

arg1 OP arg2

OP är en av -eq, -ne, -lt, -le, -gt eller -ge. Dessa aritmetiska binära operatörer returnerar true om arg1 är lika med, inte lika med, mindre än, mindre än eller lika med, större än eller större än eller lika med arg2 , respektive. Arg1 och arg2 kan vara positiva eller negativa heltal.

eller aritmetiskt uttryck:

<= >= < > jämförelse

== != jämlikhet och ojämlikhet

Varför har vi två olika sätt att jämföra två heltal? När ska man använda det?

Till exempel använder [[ 3 -lt 2 ]] villkorligt uttryck och (( 3 < 2 )) använder aritmetiskt uttryck. Båda returnerar 0 när jämförelsen är sann

Kan man jämföra två heltal om de här två metoderna alltid är omväxlande? Om ja, varför har Bash två metoder snarare än en?

Kommentarer

  • = != < <= > >= jämför strängar . 1 -eq 01 men 1 != 01 och 8 -lt 42 men 8 > 42
  • De är överbelastade i aritmetiska uttryck.
  • du ’ Du måste söka i bash-ändringsloggarna för att ta reda på när varje funktion var Lagt till. Jag misstänker att aritmetiska uttryck lades till mycket senare än testkommandot.
  • Jag frågar inte om att jämföra strängar. @muru.

Svar

Ja, vi har två olika sätt att jämföra två heltal.

Det verkar som att dessa fakta inte är allmänt accepterade i det här forumet:

  1. Inuti idiomet [ ] är operatörerna för aritmetisk jämförelse -eq, -ne, -lt, -le, -gt och -ge.

    Eftersom de också finns i ett testkommando och inuti en [[ ]].

    Ja inuti de här idiomen, =, <, etc. är strängoperatorer.

  2. Inuti idiomet (( )) är operatörerna för aritmetisk jämförelse == , !=, <, <=, > och >=.

    Nej, detta är inte en ”aritm etisk expansion ”(som börjar med en $) som $(( )). Det definieras som ett ”sammansatt kommando” i man bash.

    Ja, det följer samma regler (internt) för ”Aritmetisk expansion” men har ingen utdata, bara ett utgångsvärde. Det kan användas så här:

if (( 2 > 1 )); then ... 

Varför har vi två olika sätt att jämföra två heltal?

Jag antar att den senare (( )) utvecklades som ett enklare sätt att utföra aritmetiska tester. Det är nästan detsamma som $(( )) men har bara ingen utdata.

Varför två? Samma sak som varför vi har två printf (externa och inbyggda) eller fyra test (externa test, inbyggda test, [ och [[). Det är så att skalen växer och förbättrar något område på ett år, förbättrar andra nästa år.

När ska man använda vilket?

Det är en mycket tuff fråga för det borde inte finnas någon effektiv skillnad. Naturligtvis finns det några skillnader i hur ett [ ] arbete och ett (( )) fungerar internt, men: vilket är bättre att jämföra två heltal? Vilken som helst !.

Kan dessa två metoder alltid användas omväxlande när man jämför två heltal?

För två siffror är jag tvingad att säga ja.
Men för variabler, utvidgningar , matematiska operationer kan det finnas viktiga skillnader som bör gynna den ena eller den andra. Jag kan inte säga att absolut båda är lika. För en kan (( )) utföra flera matematiska operationer i sekvens:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi 

Om ja, varför har Bash två metoder snarare än en?

Om båda är till hjälp, varför inte ?.

Kommentarer

  • = är en uppgift och == är en jämförelse i aritmetiska utvidgningar. Frågan citerar det korrekt. Men svaret är fel.
  • Dessutom är ( inte ett reserverat ord i bash så det finns inget behov av att placera mellanslag runt ((, som motsätter sig [ eller [[

Svar

Historiskt sett fanns kommandot test först (åtminstone så långt tillbaka till Unix sjunde utgåvan 1979). Den använde operatörerna = och != för att jämföra strängar och -eq, -ne, -lt, etc. för att jämföra siffror. Till exempel är test 0 = 00 falskt, men test 0 -eq 00 är sant. Jag vet inte varför denna syntax valdes, men det kan ha varit att undvika att använda < och >, som skalet skulle ha analyseras som omdirigeringsoperatörer. Kommandot test fick en ny syntax några år senare: [ … ] motsvarar test ….

[[ … ]] villkorlig syntax, inom vilken < och > kan användas som operatörer utan att citera, lades till senare, i ksh. Det behöll bakåtkompatibilitet med [ … ], så det använde samma operatorer, men lade till < och > för att jämföra strängar (till exempel [[ 9 > 10 ]] men [[ 9 -lt 10 ]]). För mer information, se med enkel eller dubbel parentes – bash

Aritmetiska uttryck kom också senare än test -kommando,

i Korn-skalet , någon gång på 1980-talet. De följde syntaxen för C-språket, vilket var mycket populärt i Unix-kretsar. Således använde de C: s operatorer:==för jämlikhet,<=för mindre eller lika, etc.

Unix sjunde upplagan hade inte aritmetiska uttryck, men den hade expr kommandot , som också implementerade en C-liknande syntax för heltalsåtgärder, inklusive dess jämförelseoperatörer. I ett skalskript måste tecknen < och > citeras för att skydda dem från skalet, t.ex. if expr 1 \< 2; … motsvarar if test 1 -lt 2; …. Tillägget av aritmetiska uttryck till skalet gjorde mest användning av expr föråldrad, så det är inte välkänt idag.

I ett sh-skript, du ” d brukar använda aritmetiska uttryck för att beräkna ett heltal och [ … ] för att jämföra heltal.

if [ "$((x + y))" -lt "$z" ]; then … 

I en ksh , bash eller zsh-skript kan du använda ((…)) för båda.

if ((x + y < z)); then … 

[[ … ]] -formulär är användbart om du vill använda villkor som involverar andra saker än heltal.

Svar

Enligt testman-sidan, = och! = används för strängjämförelser medan uttrycken -eq, -gt, -lt, -ge, -le och -ne är heltaljämförelser. Jag har alltid följt denna konvention när jag skriver skalskript och det fungerar alltid. Var medveten om att om du har variabler i uttrycket kan du behöva citera variablerna på något sätt för att undvika att göra en nolljämförelse.

På papper gör vi jämförelser med strängar / siffror utan mycket eftertanke. En dator å andra sidan vet inte om 987 är ett tal eller en teckensträng. Du behöver de olika operatörerna för att berätta för datorn vad du ska göra så att du får rätt resultat. Det finns ytterligare information här som förklarar en del av historien. I huvudsak är variablerna otypade och har förblivit så för historisk kompatibilitet.

Kommentarer

  • I mitt inlägg, = och != är aritmetiska operatorer, medan manpage för test bara visar villkorliga expressionsoperatorer.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *