Compararea numerelor întregi: expresie aritmetică sau expresie condițională

În Bash, două numere întregi pot fi comparate folosind expresia condițională

arg1 OP arg2

OP este unul dintre -eq, -ne, -lt, -le, -gt sau -ge. Acești operatori binari aritmetici returnează adevărat dacă arg1 este egal cu, nu egal cu, mai mic decât, mai mic sau egal cu, mai mare decât sau mai mare sau egal cu arg2 , respectiv. Arg1 și arg2 pot fi numere întregi pozitive sau negative.

sau expresie aritmetică:

<= >= < > comparație

== != egalitate și inegalitate

De ce avem două modalități diferite de a compara două numere întregi? Când să folosiți care?

De exemplu, [[ 3 -lt 2 ]] folosește expresia condițională, iar (( 3 < 2 )) folosește expresia aritmetică. Ambele returnează 0 atunci când comparația este adevărată

Atunci când se compară două numere întregi, aceste două metode pot fi utilizate întotdeauna în mod interschimbabil? Dacă da, de ce Bash are mai degrabă două metode decât una?

Comentarii

  • = != < <= > >= compara șiruri . 1 -eq 01 dar 1 != 01 și 8 -lt 42 dar 8 > 42
  • Acestea sunt supraîncărcate în expresii aritmetice.
  • va trebui să „3175f49de8”>

să căutați în jurnalele de schimbări bash pentru a afla când a fost fiecare caracteristică adăugat. Bănuiesc că expresiile aritmetice au fost adăugate mult mai târziu decât comanda de testare.

  • Nu mă întreb despre compararea șirurilor. @muru.
  • Răspuns

    Da, avem două moduri diferite de a compara două numere întregi.

    Se pare că aceste fapte nu sunt acceptate pe scară largă în acest forum:

    1. În limbajul [ ] operatorii pentru comparația aritmetică sunt -eq, -ne, -lt, -le, -gt și -ge.

      De asemenea, sunt în interiorul unei comenzi de testare și în interiorul unui [[ ]].

      Da în aceste limbaje, =, < etc. sunt operatori de șiruri.

    2. În expresia (( )) operatorii pentru comparația aritmetică sunt == , !=, <, <=, > și >=.

      Nu, acesta nu este un „Aritm etic expansion „(care începe cu un $) ca $(( )). Este definit ca o „Comandă compusă” în man bash.

      Da, respectă aceleași reguli (intern) ale „expansiunii aritmetice”, dar nu are ieșire, ci doar o valoare de ieșire. Ar putea fi folosit astfel:

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

    De ce avem două modalități diferite de a compara două numere întregi?

    Cred că acesta din urmă (( )) a fost dezvoltat ca un mod mai simplu de a efectua teste aritmetice. Este aproape la fel ca $(( )), dar nu are rezultate.

    De ce două? Ei bine, la fel ca și motivul pentru care avem doi printf (extern și integrat) sau patru test (extern test, incorporat test, [ și [[). Acesta este modul în care cojile cresc, îmbunătățind o anumită zonă într-un an, îmbunătățind unele altele în anul următor.

    Când se folosește care?

    Aceasta este o întrebare foarte dificilă, deoarece nu ar trebui să existe nicio diferență efectivă. Desigur, există unele diferențe în modul în care o [ ] funcționează și o (( )) funcționează intern, dar: care este mai bine să comparați doi numere întregi? Oricare !.

    Atunci când se compară două numere întregi, aceste două metode pot fi utilizate întotdeauna interschimbabil?

    Pentru două numere sunt obligat să spun da.
    Dar pentru variabile, extinderi , operațiile matematice pot exista diferențe cheie care ar trebui să favorizeze una sau alta. Nu pot spune că absolut ambele sunt egale. În primul rând, (( )) ar putea efectua mai multe operații matematice în ordine:

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

    Dacă da, de ce are Bash mai degrabă două metode decât una?

    Dacă ambele sunt utile, de ce nu ?.

    Comentarii

    • = este o atribuire și == este o comparație în expansiunile aritmetice. Întrebarea o citează corect. Dar răspunsul este greșit.
    • De asemenea, ( nu este un cuvânt rezervat în bash, deci nu este nevoie să puneți spații în jurul (( opus [ sau [[

    Răspuns

    Din punct de vedere istoric, comanda test a existat mai întâi (cel puțin până la ediția a șaptea Unix în 1979). A folosit operatorii = și != pentru a compara șirurile și -eq, -ne, -lt etc. pentru a compara numerele. De exemplu, test 0 = 00 este fals, dar test 0 -eq 00 este adevărat. Nu știu de ce a fost aleasă această sintaxă, dar s-ar putea să fi fost să eviți utilizarea < și >, pe care ar avea-o shell-ul analizat ca operatori de redirecționare. Comanda test a primit o altă sintaxă câțiva ani mai târziu: [ … ] este echivalentă cu test ….

    Sintaxa condițională [[ … ]], în interiorul căreia < și > poate fi folosit ca operatori fără a cita, a fost adăugat mai târziu, în ksh. A păstrat compatibilitatea înapoi cu [ … ], deci a folosit aceiași operatori, dar a adăugat < și > pentru a compara șirurile (de exemplu, [[ 9 > 10 ]] dar [[ 9 -lt 10 ]]). Pentru mai multe informații, consultați folosind paranteză simplă sau dublă – bash

    Expresiile aritmetice au venit mai târziu decât test,

    în coaja Korn , la un moment dat în anii 1980. Au urmat sintaxa limbajului C, care era foarte populară în cercurile Unix. Astfel au folosit operatorii C: s==pentru egalitate,<=pentru mai puțin sau egal etc.

    Unix Seventh Edition nu avea expresii aritmetice, dar avea comanda expr , care de asemenea a implementat o Sintaxă de tip C pentru operații întregi, inclusiv operatorii săi de comparație. Într-un script shell, caracterele < și > trebuiau citate pentru a le proteja de shell, de ex. if expr 1 \< 2; … este echivalent cu if test 1 -lt 2; …. Adăugarea de expresii aritmetice la coajă a făcut ca majoritatea utilizărilor expr să fie învechite, deci nu este bine cunoscut astăzi.

    Într-un script sh, tu ” În general, utilizați expresii aritmetice pentru a calcula o valoare întreagă și [ … ] pentru a compara numere întregi.

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

    În ksh , bash sau zsh script, puteți utiliza ((…)) pentru ambele.

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

    este util dacă doriți să utilizați condiționale care implică alte lucruri decât numerele întregi.

    Răspuns

    Conform pagina man test, = și! = sunt folosite pentru comparații de șiruri, în timp ce expresiile -eq, -gt, -lt, -ge, -le și -ne sunt comparații întregi. „Am respectat întotdeauna această convenție când scriu scripturi shell și funcționează întotdeauna. Rețineți că, dacă aveți variabile în expresie, poate fi necesar să citați variabilele într-un fel pentru a evita să faceți o comparație nulă.

    Pe hârtie, facem comparații de șiruri / numere fără prea multe gânduri. Pe de altă parte, un computer nu știe dacă 987 este un număr sau un șir de caractere. Aveți nevoie de diferiți operatori pentru a spune computerului ce trebuie să faceți, astfel încât să obțineți rezultatul corect. Există câteva informații suplimentare aici care explică o parte din istorie. În esență, variabilele sunt netipate și au rămas așa pentru compatibilitatea istorică.

    Comentarii

    • În postarea mea, = și != sunt operatori aritmetici, în timp ce pagina de manual a test arată numai operatori de expresie condiționată.

    Lasă un răspuns

    Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *