Parcours
/
Bash
Bash
/
Programme
/
Arithmétique
Ar

Arithmétique en Bash

{one: "%{count} exercice", many: "%{count} d'exercices", other: "%{count} exercices"}

À propos de Arithmétique

Bash sait faire de l'arithmétique, mais uniquement avec des entiers. Si tu as besoin de calculs sur des nombres à virgule flottante, il te faudra faire appel à un programme externe (comme awk ou bc).

Les opérateurs arithmétiques sont listés (par ordre de priorité) dans le manuel : Shell Arithmetic.

De plus, Bash ne fait de l'arithmétique qu'à certains endroits précis (appelés « contextes » arithmétiques).

L'expansion arithmétique

L'expansion arithmétique ressemble à la substitution de commande, mais avec des doubles parenthèses.

$(( expression ))

Cette syntaxe produit, après expansion, le résultat de l'évaluation de l'expression. On l'utilise couramment pour récupérer le résultat dans une variable :

x=$(( 3 + 4 ))
Note

Le nombre d'espaces à l'intérieur des parenthèses est à ta convenance. C'est une question de style et de lisibilité.

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

Ton sympathique auteur aime ajouter des espaces pour que l'expression arithmétique soit plus visible entre les parenthèses.

Le conditionnel arithmétique

Le conditionnel arithmétique s'écrit entre doubles parenthèses, sans le $ initial :

(( expression ))

Cette forme ne produit pas de résultat après expansion. En revanche, elle produit un code de sortie.

  • Le code de sortie vaut 0 (succès) si le résultat de l'expression est non nul.
  • Le code de sortie vaut 1 (échec) si le résultat de l'expression est nul.
Note

À l'intérieur de ((, Bash utilise la même notion de vrai/faux que le langage C : zéro est faux, une valeur non nulle est vraie. C'est l'inverse de la façon dont Bash évalue les codes de sortie !

Cette syntaxe s'utilise généralement à deux endroits :

  1. comme partie COMMANDE d'une instruction if ou d'une boucle while.

    if (( x == y - 1 )); then ...
    while (( y > 0 )); do ...
    
  2. comme commande autonome pour modifier la valeur d'une variable.

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

    Fais attention si tu utilises l'arithmétique de cette façon avec set -e. Si l'expression vaut zéro, le code de sortie sera non nul et Bash s'arrêtera.

    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"
    

    Pour une discussion plus approfondie sur l'opérateur ++, consulte cet article sur Postincrement vs Preincrement

Les autres endroits où l'on est en contexte arithmétique

Il existe quelques autres endroits qui constituent des contextes arithmétiques :

  • La boucle for arithmétique.

    for (( i = 0; i < 10; i++ )); do
        echo "$i"
    done
    
  • La partie indice d'un tableau indexé numériquement.

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

    Pour en savoir plus sur les tableaux, lis la fiche de concept Tableaux.

  • Les parties décalage et longueur de l'expansion ${var:offset:length}.

  • La commande intégrée let.

    • Note que (( expression )) est préférable à let "expresson". Contrairement à la construction du conditionnel arithmétique, l'expression let est soumise à l'expansion des noms de fichiers et au découpage des mots, et elle doit être protégée par des guillemets.
  • L'affectation de variable, lorsque la variable possède l'« attribut entier ».

    # 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

    De l'avis de l'auteur, declare -i a un usage limité. Son principal intérêt est de permettre une arithmétique « nue » (sans la syntaxe d'expression arithmétique). Cela peut semer la confusion chez les personnes qui lisent ton code, car les expressions arithmétiques y sont évaluées à des endroits inattendus.

Utiliser des variables dans une expression arithmétique

Voici un aspect des contextes arithmétiques qui améliore la lisibilité.

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

As-tu remarqué que les signes dollar $ sont absents des variables dans l'expression arithmétique ? Bash t'autorise à faire cela. Cela rend les expressions bien plus faciles à lire.

Le manuel dit :

Dans une expression, les variables du shell peuvent aussi être référencées par leur nom, sans utiliser la syntaxe d'expansion des paramètres.

Cela fonctionne même pour les éléments d'un tableau :

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

Mais les autres expressions de paramètres doivent utiliser leur syntaxe spéciale. Par exemple, doubler la longueur d'une string :

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

Et les paramètres positionnels doivent faire de même. Si les deux premiers paramètres positionnels représentent la largeur et la hauteur :

area=$(( $1 * $2 ))
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet