Vergleich von Dezimalzahlen in Bash

Vergleich von Dezimalzahlen in Bash

Bei meiner Suche heute Morgen ging es darum, wie ich zwei Dezimalzahlen in Bash vergleichen kann, und ich bin auf diese Antwort gestoßen:So vergleichen Sie mit Gleitkommazahlen in einem Shell-Skript. Dieses hier beinhaltet jedoch nichtdiese Antwort hier:

$ [[ ((3.56 < 2.90)) ]]; echo $?
1
$ [[ ((3.56 < 4.90)) ]]; echo $?
0

Wenn man bedenkt, dass die Antwort heruntergevotet wurde und es sich um eine Art ungewöhnlichen Bashismus handelt, ist die Genauigkeit dieser arithmetischen Auswertung vertrauenswürdig?

Antwort1

bashversteht keine Gleitkommazahlen.
Zitat aus bashder Manualpage, AbschnittArithmetische Auswertung:

Die Auswertung erfolgt in Ganzzahlen mit fester Breite […].

Also ((3 < 4))oder ((3 < 2))sind eigentlich korrekte Rechenausdrücke. Sie können Folgendes eingeben:

$ echo "$((3 < 4)) -- $((3 < 2))"

Ausgabe:1 -- 0

Gibt aber $ echo $((3.3 < 3.6))eine Syntaxfehlermeldung zurück. In Ihrem Beispiel vergleichen Sie tatsächlich Zeichenfolgen. Daher einige Beispiele:

$ [[ ((3.56 < 04.90)) ]]; echo $?

Ausgabe:1

Antwort2

Der Inhalt [[...]] <dient zum Zeichenfolgenvergleich.

Also vergleicht [[ 3.56 < 2.90 ]]oder [[ (3.56 < 2.90) ]]oder [[ ((3.56 < 2.90)) ]]oder [[ (((3.56 < 2.90))) ]]... einfach die 3.56Zeichenfolge mit der 2.90Zeichenfolge lexikalisch (und lexikalisch ist beispielsweise „ 3größer als“ ).10

Für den Vergleich ganzer Zahlen ist es [[ 3 -lt 2 ]]oder (( 3 < 2 )). Für einen Vergleich von Gleitkommazahlen benötigen Sie ksh93, zshoder yashoder ein externes Dienstprogramm wie awkoder perl; bashdas geht nicht.

Sie könnten beispielsweise eine Funktion wie folgt definieren:

compare() (IFS=" "
  exec awk "BEGIN{if (!($*)) exit(1)}"
)

Sie können diese beispielsweise wie folgt verwenden:

if compare '1.5*10 < 1e3'; then
  echo less
fi

Oder was das betrifft:

if compare '"bar" < "foo"'...

um Zeichenfolgenvergleiche durchzuführen.

Übergeben Sie keine unkontrollierten, von außen bereitgestellten Daten an diese compareFunktion, da dies eine Sicherheitslücke durch Befehlsinjektion darstellen würde (die Daten werden als awkCode interpretiert und können beispielsweise awkdamit Befehle ausführen ).system()

verwandte Informationen