746 votes

Comment augmenter une variable en bash ?

J'ai essayé d'incrémenter une variable numérique en utilisant à la fois var=$var+1 et var=($var+1) sans succès. La variable est un nombre, bien que bash semble la lire comme une chaîne de caractères.

Version de Bash 4.2.45(1)-release (x86_64-pc-linux-gnu) sur Ubuntu 13.10.

1138voto

Radu Rădeanu Points 156862

Il y a plus d'une façon d'incrémenter une variable en bash, mais ce que vous avez essayé ne fonctionnera pas.

Vous pouvez utiliser, par exemple, l'expansion arithmétique:

var=$((var+1))
((var=var+1))
((var+=1))
((var++))

Ou vous pouvez utiliser let:

let "var=var+1"
let "var+=1"
let "var++"

Voir aussi: https://tldp.org/LDP/abs/html/dblparens.html.

209voto

Paul Tanzini Points 3587
var=$((var + 1))

Les opérations arithmétiques en bash utilisent la syntaxe $((...)).

114voto

Keith Reynolds Points 419

Différentes options pour incrémenter de 1, et analyse des performances

Merci à Radu Radeanu's answer qui propose les façons suivantes d'incrémenter une variable en bash :

var=$((var+1))
((var=var+1))
((var+=1))
((var++))
let "var=var+1"
let "var+=1" 
let "var++"

Il existe d'autres façons également. Par exemple, consultez les autres réponses à cette question.

let var++
var=$((var++))
((++var))
{
    declare -i var
    var=var+1
    var+=1
}
{
    i=0
    i=$(expr $i + 1)
}

Avoir autant d'options soulève ces deux questions :

  1. Y a-t-il une différence de performance entre elles ?
  2. Si oui, laquelle performe le mieux ?

Code de test de performance incrémentale :

#!/bin/bash

# Pour se concentrer exclusivement sur la performance de chaque type d'instruction d'incrémentation
# nous devrions exclure les boucles while de bash des mesures de performance. Ainsi, mesurons le temps
# des scripts individuels qui incrémentent $i à leur manière unique.

# Déclarer i comme un entier pour les tests 12 et 13.
echo > t12 'declare -i i; i=i+1'
echo > t13 'declare -i i; i+=1'
# Définir i pour le test 14.
echo > t14 'i=0; i=$(expr $i + 1)'

x=100000
while ((x--)); do
    echo >> t0 'i=$((i+1))'
    echo >> t1 'i=$((i++))'
    echo >> t2 '((i=i+1))'
    echo >> t3 '((i+=1))'
    echo >> t4 '((i++))'
    echo >> t5 '((++i))'
    echo >> t6 'let "i=i+1"'
    echo >> t7 'let "i+=1"'
    echo >> t8 'let "i++"'
    echo >> t9 'let i=i+1'
    echo >> t10 'let i+=1'
    echo >> t11 'let i++'
    echo >> t12 'i=i+1'
    echo >> t13 'i+=1'
    echo >> t14 'i=$(expr $i + 1)'
done

for script in t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14; do
    line1="$(head -1 "$script")"
    printf "%-24s" "$line1"
    { time bash "$script"; } |& grep user
    # Puisque stderr est redirigé vers grep ci-dessus, cela confirmera
    # qu'il n'y a pas d'erreurs lors de l'exécution de la commande :
    eval "$line1"
    rm "$script"
done

Résultats:

i=$((i+1))              user    0m0.992s
i=$((i++))              user    0m0.964s
((i=i+1))               user    0m0.760s
((i+=1))                user    0m0.700s
((i++))                 user    0m0.644s
((++i))                 user    0m0.556s
let "i=i+1"             user    0m1.116s
let "i+=1"              user    0m1.100s
let "i++"               user    0m1.008s
let i=i+1               user    0m0.952s
let i+=1                user    0m1.040s
let i++                 user    0m0.820s
declare -i i; i=i+1     user    0m0.528s
declare -i i; i+=1      user    0m0.492s
i=0; i=$(expr $i + 1)   user    0m5.464s

Conclusion:

Il semble que bash soit le plus rapide en exécutant i+=1 lorsque $i est déclaré comme un entier. Les instructions let semblent particulièrement lentes, et expr est de loin la plus lente car elle n'est pas intégrée à bash.

21voto

tphelican Points 311

Il y a aussi ceci :

var=`expr $var + 1`

Prenez note des espaces et aussi ` n'est pas '

Alors que les réponses de Radu, et les commentaires, sont exhaustifs et très utiles, ils sont bash-spécifiques. Je sais que vous avez spécifiquement demandé à propos de bash, mais je me permets d'intervenir car j'ai trouvé cette question lorsque je cherchais à faire la même chose en utilisant sh dans busybox sous uCLinux. Cela est portable au-delà de bash.

11voto

Radon Rosborough Points 254

Si vous déclarez $var comme un entier, alors ce que vous avez essayé la première fois fonctionnera en réalité :

$ declare -i var=5
$ echo $var
5
$ var=$var+1
$ echo $var
6

Référence: Types de variables, Guide Bash pour débutants

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X