Frage Wie erhöhe ich eine Variable in bash?


Ich habe versucht, eine numerische Variable mit beiden zu inkrementieren var=$var+1 und var=($var+1) ohne Erfolg. Die Variable ist eine Zahl, obwohl bash sie als String zu lesen scheint.

Bash Version 4.2.45 (1) -Release (x86_64-pc-linux-gnu) unter Ubuntu 13.10.


455
2017-12-03 16:34


Ursprung




Antworten:


Es gibt mehr als eine Möglichkeit, eine Variable in bash zu inkrementieren, aber was Sie versucht haben, ist nicht korrekt.

Sie können zum Beispiel verwenden arithmetische Expansion:

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

Oder du kannst es benutzen let:

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

Siehe auch: http://tldp.org/LDP/abs/html/dblparens.html.


720
2017-12-03 16:39



oder ((++var)) oder ((var=var+1)) oder ((var+=1)). - gniourf_gniourf
oder var = $ (ausdr $ var + 1) - Javier López
Seltsamerweise var=0; ((var++)) Gibt währenddessen einen Fehlercode zurück var=0; ((var++)); ((var++)) nicht. Irgendeine Idee warum? - phunehehe
@phunehehe Schau dir an help '(('. Die letzte Zeile sagt: Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise. - Radu Rădeanu
ist es sicher zu benutzen let var++, ohne die Anführungszeichen? - wjandrea


var=$((var + 1))

Arithmetik in bash verwendet $((...)) Syntax.


101
2017-12-03 16:38



Weitaus besser als die angenommene Antwort. In nur 10% so viel Platz, haben Sie genug Beispiele geliefert (eins ist viel - neun ist zu viel auf den Punkt, wenn Sie gerade zeigen), und Sie haben uns genügend Informationen zur Verfügung gestellt, um das zu wissen ((...))ist der Schlüssel zur Verwendung von Arithmetik in bash. Ich wusste nicht, dass ich mir nur die akzeptierte Antwort ansah - ich dachte, es gäbe eine merkwürdige Menge von Regeln bezüglich der Reihenfolge der Operationen oder etwas, das zu allen Klammern in der akzeptierten Antwort führt. - ArtOfWarfare


Performance-Analyse verschiedener Optionen

Dank an Radu Rădeanus Antwort Das bietet die folgenden Möglichkeiten, eine Variable in bash zu inkrementieren:

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

Es gibt auch andere Möglichkeiten. Schauen Sie sich zum Beispiel die anderen Antworten zu dieser Frage an.

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

So viele Optionen führen zu diesen beiden Fragen:

  1. Gibt es einen Leistungsunterschied zwischen ihnen?
  2. Wenn ja, welche, welche Leistung am besten?

Inkrementeller Leistungstestcode:

#!/bin/bash

# To focus exclusively on the performance of each type of increment
# statement, we should exclude bash performing while loops from the
# performance measure. So, let's time individual scripts that
# increment $i in their own unique way.

# Declare i as an integer for tests 12 and 13.
echo > t12 'declare -i i; i=i+1'
echo > t13 'declare -i i; i+=1'
# Set i for 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
    # Since stderr is being piped to grep above, this will confirm
    # there are no errors from running the command:
    eval "$line1"
    rm "$script"
done

Ergebnisse:

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

Fazit:

Es scheint, dass bash am schnellsten ist i+=1 wann $i wird als Integer deklariert. let Aussagen scheinen besonders langsam und expr ist bei weitem die langsamste, weil es nicht eingebaut ist.


62
2017-07-31 17:15



Scheinbar korreliert die Geschwindigkeit mit der Befehlslänge. Ich frage mich, ob die Befehle die gleichen Funktionen aufrufen. - MatthewRock
i=(expr ...) ist ein Syntaxfehler. Hast du gemeint i=$(expr ...)? - muru
@muru behoben, und fügte ein Häkchen in die for-Schleife. - wjandrea


Es gibt auch das:

var=`expr $var + 1`

Beachten Sie die Räume und auch ` ist nicht "

Radus Antworten und die Kommentare sind zwar erschöpfend und sehr hilfreich, aber sie sind bash-spezifisch. Ich weiß, dass du speziell nach Bash gefragt hast, aber ich dachte mir, dass ich reinkommen würde, seit ich diese Frage gefunden habe, als ich das gleiche mit sh in busybox unter uCLinux machen wollte. Dieser Portable jenseits der Bash.


14
2017-08-22 23:11



Sie können auch verwenden i=$((i+1)) - wjandrea
Wenn Prozesssubstitution $(...) ist in dieser Shell verfügbar, ich würde es stattdessen empfehlen. - Radon Rosborough


Wenn Sie erklären $var als Ganzzahl, dann wird das, was Sie beim ersten Mal versucht haben, auch funktionieren:

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

Referenz: Arten von Variablen, Bash Guide für Anfänger


9
2017-12-06 22:19





Es gibt eine Methode, die in allen Antworten fehlt - bc

$ VAR=7    
$ bc <<< "$VAR+2"
9
$ echo $VAR
7
$ VAR=$( bc <<< "$VAR+1" )
$ echo $VAR
8

bc ist spezifiziert durch POSIX Standard, sollte also auf allen Versionen von Ubuntu und POSIX-konformen Systemen vorhanden sein. Das <<< Umleitung könnte geändert werden echo "$VAR" | bc für die Portabilität, aber da die Frage fragt nach bash - Es ist in Ordnung, nur zu verwenden <<<.


6
2018-02-23 13:58





Der Rückkehrcode 1 Problem ist für alle Standardvarianten vorhanden (let, (()), etc.). Dies verursacht häufig Probleme, z. B. in Skripten, die verwenden set -o errexit. Hier ist, was ich verwende, um Fehlercode zu verhindern 1 von mathematischen Ausdrücken, die auswerten 0;

math() { (( "$@" )) || true; }

math a = 10, b = 10
math a++, b+=2
math c = a + b
math mod = c % 20
echo $a $b $c $mod
#11 12 23 3

4