Ganzzahlen vergleichen: arithmetischer Ausdruck oder bedingter Ausdruck

20

In Bash können zwei Ganzzahlen mithilfe eines bedingten Ausdrucks verglichen werden

arg1 OP arg2

OP ist ein von -eq, -ne, -lt, -le, -gt, oder -ge. Diese arithmetischen Binäroperatoren geben true zurück, wenn arg1 gleich, nicht gleich, kleiner oder gleich, größer oder größer oder gleich arg2 ist. Arg1 und arg2 können positive oder negative ganze Zahlen sein.

oder arithmetischer Ausdruck:

<= >= < > Vergleich

== != Gleichheit und Ungleichheit

Warum haben wir zwei verschiedene Möglichkeiten, um zwei ganze Zahlen zu vergleichen? Wann welche verwenden?

Zum Beispiel [[ 3 -lt 2 ]]verwendet bedingten Ausdruck, und (( 3 < 2 ))verwendet arithmetischen Ausdruck. Beide geben 0 zurück, wenn der Vergleich wahr ist

Können diese beiden Methoden beim Vergleich zweier Ganzzahlen immer synonym verwendet werden? Wenn ja, warum hat Bash zwei Methoden anstatt einer?

Tim
quelle
1
= != < <= > >=Saiten vergleichen . 1 -eq 01aber 1 != 01und 8 -lt 42doch8 > 42
dave_thompson_085
Sie sind in arithmetischen Ausdrücken überladen.
Tim
1
Sie müssen in den Bash-Änderungsprotokollen suchen, um herauszufinden, wann die einzelnen Funktionen hinzugefügt wurden. Ich vermute, dass die arithmetischen Ausdrücke viel später als der Testbefehl hinzugefügt wurden.
Glenn Jackman
Ich frage nicht nach dem Vergleich von Saiten. @muru.
Tim

Antworten:

28

Ja, wir haben zwei verschiedene Möglichkeiten, zwei ganze Zahlen zu vergleichen.

Es scheint, dass diese Fakten in diesem Forum nicht allgemein akzeptiert werden:

  1. Im Innern des Idiom [ ]die Operatoren für arithmetischen Vergleich sind -eq, -ne, -lt, -le, -gtund -ge.

    Da sie sich auch innerhalb eines Testbefehls und innerhalb eines [[ ]].

    Ja innerhalb dieser Idiome =, <etc. sind String - Operatoren.

  2. Im Innern des Idiom (( ))die Operatoren für arithmetischen Vergleich sind ==, !=, <, <=, >, und >=.

    Nein, dies ist keine "arithmetische Erweiterung" (die mit a beginnt $) als $(( )). Es wird in man bash als "zusammengesetzter Befehl" definiert.

    Ja, es folgt den gleichen Regeln (intern) der "arithmetischen Erweiterung", hat aber keine Ausgabe, nur einen Exit-Wert. Es könnte so verwendet werden:

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

Warum haben wir zwei verschiedene Möglichkeiten, um zwei ganze Zahlen zu vergleichen?

Ich vermute, dass letzteres (( ))als einfachere Methode zur Durchführung von arithmetischen Tests entwickelt wurde. Es ist fast das gleiche wie das $(( )), hat aber einfach keine Ausgabe.

Warum zwei? Nun das gleiche wie , warum haben wir zwei printf(extern und builtin) oder vier Test (extern test, builtin test, [und [[). Auf diese Weise wachsen die Muscheln und verbessern einige Bereiche in einem Jahr, andere verbessern sich im nächsten Jahr.

Wann welche verwenden?

Das ist eine sehr schwierige Frage, denn es sollte keinen wirksamen Unterschied geben. Natürlich gibt es einige Unterschiede in der Art [ ]und Weise einer Arbeit und einer (( ))Arbeit im Inneren, aber: Was ist besser, um zwei ganze Zahlen zu vergleichen? Jeder !.

Können diese beiden Methoden beim Vergleich zweier Ganzzahlen immer synonym verwendet werden?

Für zwei Zahlen bin ich gezwungen, ja zu sagen.
Bei Variablen, Erweiterungen und mathematischen Operationen kann es jedoch wesentliche Unterschiede geben, die den einen oder anderen begünstigen sollten. Ich kann nicht sagen, dass absolut beide gleich sind. Zum einen (( ))könnten die folgenden Rechenoperationen nacheinander ausgeführt werden:

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

Wenn ja, warum hat Bash zwei Methoden anstatt einer?

Wenn beides hilfreich ist, warum nicht?

Yurij Goncharuk
quelle
1
=ist eine Aufgabe und ==ein Vergleich in arithmetischen Erweiterungen. Die Frage zitiert es richtig. Aber die Antwort ist falsch.
16.
12

In der testVergangenheit existierte der Befehl zuerst (mindestens bis zur siebten Unix-Ausgabe 1979). Es verwendet die Operatoren =und !=Zeichenfolgen zu vergleichen, und -eq, -ne, -ltetc. Zahlen zu vergleichen. Zum Beispiel test 0 = 00ist falsch, ist aber test 0 -eq 00wahr. Ich weiß nicht, warum diese Syntax gewählt wurde, aber es könnte sein, dass die Verwendung von <und >vermieden wurde, was die Shell als Umleitungsoperatoren analysiert hätte. Der testBefehl bekam eine andere Syntax ein paar Jahre später: [ … ]entspricht test ….

Die [[ … ]]bedingte Syntax, in dessen Innerem <und >können als Betreiber verwendet werden , ohne zu zitieren, wurde später hinzugefügt, in KSH. Es wurde die Abwärtskompatibilität mit beibehalten [ … ], daher wurden dieselben Operatoren verwendet, jedoch Zeichenfolgen hinzugefügt <und >verglichen (z. B. [[ 9 > 10 ]]aber [[ 9 -lt 10 ]]). Weitere Informationen finden Sie unter Verwenden der einfachen oder doppelten Klammer - bash

Arithmetische Ausdrücke kamen auch später als der testBefehl in der Korn-Shell , irgendwann in den 1980er Jahren. Sie folgten der Syntax der C-Sprache, die in Unix-Kreisen sehr beliebt war. Also benutzten sie die Operatoren von C: ==für Gleichheit, <=für weniger oder gleich usw.

Unix Seventh Edition verfügte nicht über arithmetische Ausdrücke, sondern über den exprBefehl , der auch eine C-ähnliche Syntax für Ganzzahloperationen einschließlich der Vergleichsoperatoren implementierte. In einem Shell-Skript müssen die Zeichen <und >in Anführungszeichen gesetzt werden, um sie vor der Shell zu schützen, z . B. if expr 1 \< 2; …entspricht if test 1 -lt 2; …. Das Hinzufügen von arithmetischen Ausdrücken zur Shell machte die meisten Verwendungen exprüberflüssig, so dass es heute nicht mehr bekannt ist.

In einem sh-Skript verwenden Sie im Allgemeinen arithmetische Ausdrücke, um einen Ganzzahlwert zu berechnen und Ganzzahlen [ … ]zu vergleichen.

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

In einem ksh-, bash- oder zsh-Skript können Sie ((…))beides verwenden.

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

Das [[ … ]]Formular ist nützlich, wenn Sie Bedingungen verwenden möchten, bei denen es sich nicht um Ganzzahlen handelt.

Gilles 'SO - hör auf böse zu sein'
quelle
1

Laut Testmanpage werden = und! = Für Zeichenfolgenvergleiche verwendet, während die Ausdrücke -eq, -gt, -lt, -ge, -le und -ne Ganzzahlvergleiche sind. Ich habe mich beim Schreiben von Shell-Skripten immer an diese Konvention gehalten und sie funktioniert immer. Beachten Sie, dass Sie bei Variablen im Ausdruck die Variablen möglicherweise in Anführungszeichen setzen müssen, um einen Nullvergleich zu vermeiden.

Auf dem Papier führen wir Zeichenfolgen- / Zahlenvergleiche ohne viel Nachdenken durch. Ein Computer hingegen weiß nicht, ob 987 eine Zahl oder eine Zeichenfolge ist. Die verschiedenen Bediener müssen dem Computer mitteilen, was zu tun ist, damit Sie das richtige Ergebnis erzielen. Es gibt einige zusätzliche Informationen hier , die etwas von der Geschichte erklärt. Im Wesentlichen sind die Variablen untypisiert und aus Gründen der historischen Kompatibilität unverändert geblieben.

signal7
quelle
In meinem Beitrag = und !=sind arithmetische Operatoren, während die Manpage von testnur bedingte Ausdrucksoperatoren zeigt.
Tim