Tracks
/
Bash
Bash
/
Lehrplan
/
Arithmetik
Ar

Arithmetik in Bash

{one: "1 Übung", other: "%{count} Übungen"}

Über Arithmetik

Bash kann rechnen, aber nur mit Ganzzahlen. Wenn du mit Gleitkommazahlen rechnen musst, musst du ein externes Programm aufrufen (wie awk oder bc).

Die arithmetischen Operatoren sind (in der Reihenfolge ihrer Priorität) im Handbuch aufgelistet: Shell-Arithmetik.

Außerdem führt Bash Arithmetik nur an bestimmten Stellen aus (den sogenannten arithmetischen „Kontexten“).

Arithmetische Expansion

Die arithmetische Expansion sieht aus wie die Kommandosubstitution, aber mit doppelten runden Klammern.

$(( expression ))

Diese Syntax expandiert zum Ergebnis der Auswertung des Ausdrucks. Sie wird häufig verwendet, um das Ergebnis in einer Variablen zu speichern:

x=$(( 3 + 4 ))
Note

Wie viel Leerraum du innerhalb der Klammern verwendest, bleibt dir überlassen. Das ist eine Frage des Stils und der Lesbarkeit.

x=$(( 3 + 4 ))
y=$((5+6))

Dein freundlicher Autor fügt gerne Leerzeichen hinzu, damit der arithmetische Ausdruck innerhalb der Klammern besser sichtbar ist.

Arithmetische Bedingung

Die arithmetische Bedingung wird innerhalb doppelter runder Klammern ohne das führende $ ausgeführt:

(( expression ))

Sie expandiert nicht zum Ergebnis. Sie erzeugt jedoch einen Exit-Status.

  • Der Exit-Status ist 0 (Erfolg), wenn das Ergebnis des Ausdrucks ungleich null ist.
  • Der Exit-Status ist 1 (Fehler), wenn das Ergebnis des Ausdrucks null ist.
Note

Innerhalb von (( verwendet Bash dasselbe Verständnis von wahr/falsch wie die Sprache C: null ist falsch, ungleich null ist wahr. Das ist das Gegenteil davon, wie Bash Exit-Status auswertet!

Diese Syntax wird typischerweise an zwei Stellen verwendet:

  1. als COMMAND-Teil einer if-Anweisung oder einer while-Schleife.

    if (( x == y - 1 )); then ...
    while (( y > 0 )); do ...
    
  2. als eigenständiger Befehl, um den Wert einer Variablen zu ändern.

    (( x = x + 1 ))
    echo "new value for x is $x"
    
    Caution

    Sei vorsichtig, wenn du Arithmetik auf diese Weise zusammen mit set -e verwendest. Wenn der Ausdruck zu null ausgewertet wird, ist der Exit-Status ungleich null und Bash beendet sich.

    x=0
    (( x++ ))
    echo "you will see this"
    
    set -e
    x=0
    (( x++ ))
    echo "shell exits on the previous line; you won't see this"
    

    Eine ausführlichere Diskussion über den ++-Operator findest du in diesem Artikel über Postincrement vs Preincrement

Weitere Stellen mit Arithmetik-Kontext

Es gibt noch ein paar weitere Stellen, die Arithmetik-Kontexte sind:

  • Die arithmetische for-Schleife.

    for (( i = 0; i < 10; i++ )); do
        echo "$i"
    done
    
  • Der Index-Teil eines numerisch indizierten Arrays.

    echo "The next element is ${array[x + 1]}"
    # ................................^^^^^
    

    Mehr über Arrays erfährst du im Konzeptdokument zu Arrays.

  • Der Offset- und der Längen-Teil der Expansion ${var:offset:length}.

  • Der eingebaute Befehl let.

    • Beachte, dass (( expression )) gegenüber let "expresson" bevorzugt wird. Anders als das arithmetische Bedingungskonstrukt unterliegt der let-Ausdruck der Dateinamen-Expansion und der Wortaufteilung, und er muss in Anführungszeichen gesetzt werden.
  • Die Variablenzuweisung, wenn die Variable das „Ganzzahl-Attribut“ hat.

    # variable x does not have the integer attribute
    x="3 + 4"
    declare -p x      # => declare -- x="3 + 4"
    
    # variable y has the integer attribute
    declare -i y
    y="4 + 5"
    declare -p y      # => declare -i y="9"
    
    Note

    Der Autor ist der Meinung, dass declare -i nur begrenzt nützlich ist. Ihr Hauptvorteil ist, dass sie „nackte“ Arithmetik erlaubt (ohne die Syntax für arithmetische Ausdrücke). Das kann bei Lesern deines Codes für Verwirrung sorgen, weil arithmetische Ausdrücke an unerwarteten Stellen ausgewertet werden.

Variablen in arithmetischen Ausdrücken verwenden

Hier ist ein Aspekt der Arithmetik-Kontexte, der die Lesbarkeit verbessert.

height=10
width=20
area=$(( height * width ))

Ist dir aufgefallen, dass die $-Dollarzeichen bei den Variablen im arithmetischen Ausdruck fehlen? Bash erlaubt dir das. Das macht Ausdrücke viel leichter lesbar.

Im Handbuch steht:

Innerhalb eines Ausdrucks können Shell-Variablen auch über ihren Namen referenziert werden, ohne die Syntax der Parameterexpansion zu verwenden.

Das funktioniert sogar für Array-Elemente:

point1=(10 15)  # these are (x, y) coordinates
point2=(20 7)
distance_squared=$(( (point1[0] - point2[0])**2 + (point1[1] - point2[1])**2 ))

Andere Parameterausdrücke müssen jedoch ihre spezielle Syntax verwenden. Zum Beispiel die Verdopplung der Länge eines Strings:

s="hello world"
len=$(( ${#s} * 2 ))

Und Positionsparameter müssen das ebenfalls. Wenn die ersten beiden Positionsparameter Breite und Höhe darstellen:

area=$(( $1 * $2 ))
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab