Unterschied zwischen let, expr und $ []

23

Ich möchte wissen, was genau der Unterschied ist

a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )

Alle 4 ordnen die Variable a mit 2 zu, aber was ist der Unterschied?

Was ich bisher herausgefunden habe, ist, dass expr langsamer ist, weil es sich nicht um eine tatsächlich eingebaute Shell handelt. Aber nicht mehr als das.

ADDB
quelle

Antworten:

25

Alle diese beschäftigen sich mit Arithmetik, aber auf unterschiedliche Weise und die Variable wird auf unterschiedliche Weise erstellt. Einige davon sind spezifisch für bashMuscheln, andere nicht.

  • $((...))heißt arithmetische Expansion , die typisch für die bashund kshMuscheln ist. Dies ermöglicht einfache Ganzzahlarithmetik , jedoch keine Gleitkommazahlen. Das Ergebnis des Ausdrucks ersetzt den Ausdruck, wie er sein echo $((1+1))würdeecho 2
  • ((...))wird als arithmetische Auswertung bezeichnet und kann als Teil von if ((...)); thenoder while ((...)) ; doAnweisungen verwendet werden. Die arithmetische Erweiterung $((..))ersetzt die Ausgabe der Operation und kann verwendet werden, um Variablen wie in zuzuweisen i=$((i+1)), kann jedoch nicht in bedingten Anweisungen verwendet werden.
  • $[...] ist die alte Syntax für arithmetische Erweiterung, die veraltet ist. Siehe auch . Dies wurde wahrscheinlich beibehalten, damit alte bashSkripte nicht kaputt gehen. Das hat nicht geklappt ksh93, daher denke ich, dass diese Syntax bash-spezifisch ist. HINWEIS : Leerzeichen sind hier sehr wichtig. verwechseln Sie nicht $[1+1]mit Sachen wie [ $a -eq $b ]. Das [mit Leerzeichen wird als testBefehl bezeichnet und wird normalerweise in entscheidungsrelevanten Teilen angezeigt. Es ist sehr unterschiedlich in Verhalten und Zweck.
  • letist ein bashund kshSchlüsselwort, das die Erstellung von Variablen mit einfacher arithmetischer Auswertung ermöglicht. Wenn Sie versuchen, dort eine Zeichenfolge zuzuweisen let a="hello world", wird ein Syntaxfehler angezeigt. Funktioniert in bashund ksh93.
  • $(...)ist die Befehlsersetzung, bei der Sie buchstäblich die Ausgabe eines Befehls nehmen und einer Variablen zuweisen. Ihr Befehl hier ist expr, dass Stellungsargumente verwendet werden expr arg1 arg2 arg3, Leerzeichen also wichtig sind. Es ist wie ein kleiner Befehlszeilenrechner für Ganzzahl-Arithmetik, plus ein paar Sachen vom Typ True / False und Regex. Dies ist ein Shell-neutraler Befehl.

Erwähnenswert ist auch, dass die arithmetische Erweiterung und die Befehlssubstitution im POSIX-Standard festgelegt sind , während letund $[...]nicht.

Sergiy Kolodyazhnyy
quelle
1
((...))tatsächlich kann für Aufgaben verwendet werden bash, kshund zsh: n=10; ((n+=10)); echo $ndruckt 20 und ((x=1)); echo $xDrucke 1
Alexej Magura
1
@ Alexej Vielen Dank. Antwort aktualisiert, dieser Teil entfernt
Sergiy Kolodyazhnyy vor
11
  • letBefehl führt eine arithmetische Auswertung durch und ist eine eingebaute Shell.

    • Führen Sie diesen Befehl aus und Sie erhalten nichts (nur auswertet):

      let 1+2
  • $(( ))wird verwendet, um eine arithmetische Erweiterung durchzuführen : Lesen Sie hier

    • Führen Sie dieses aus und Sie werden eine Fehlermeldung erhalten (wegen der Erweiterung):

      $((1+2))
  • $[ ] ist die alte Syntax für die arithmetische Erweiterung:

    Das alte Format $ [Ausdruck] ist veraltet und wird in der kommenden Bash entfernt. Bash Man Page

  • expr ist ein binärer Befehl, wenn Sie eine arithmetische Erweiterung innerhalb einer Befehlssubsituation durchführen möchten, können Sie ihn verwenden:

    echo $(expr 1 + 2) 
    echo `expr 1 + 2`
Ravexina
quelle
4

Da in einigen der obigen Antworten ausdrücklich ksh93darauf hingewiesen wird, dass Gleitkomma-Berechnungen möglich sind, z.

$ print $((1.0/3)) 
0.333333333333333333

Sie können die Genauigkeit der Ausgabe mit printf steuern, z.

$ printf "%.4f\n" $((1.0/3))
0.3333

Mindestens ein Argument muss wie oben als Gleitkommazahl angegeben werden. Wenn beide als Ganzzahlen angegeben sind, wird nur eine Ganzzahlberechnung durchgeführt, z.

$ print $((1/3))  
0

Dies kann hilfreich sein, wenn Sie Gleitkomma-Mathematik in einem Shell-Skript benötigen, da Sie den Aufruf eines externen Befehls vermeiden können.

Niesen
quelle
Es kommt mir vor, dass Sie interessiert sein könnten, eine Antwort an zu senden. Kann ich Brüche / Dezimalstellen in einem Bash-Skript verwenden? Trotz des Titels denke ich, dass der Kontext klar macht, dass andere Muscheln im Bourne-Stil relevant sind, weshalb ich eine zshAntwort gepostet habe . Da kshund basheinander (im Allgemeinen) ähnlicher sind als beides zsh, scheint mir eine kh93Antwort auf diese Frage sehr nützlich zu sein.
Eliah Kagan
1

letfunktioniert nicht in cron Ich denke, das liegt an letseiner eigenen Umgebung. Verwenden Sie, $((...))da es POSIX ist. Beispielsweise,

let x=1+2
echo x=$x

in cron ergibt "x =", aber "x = 3", wenn von der Shell ausgeführt.

x=$((1+2))
echo x=$x

ergibt in allen Fällen "x = 3".

SparkEV
quelle