Bir değişken bash olarak nasıl artırılır?


609

Ben ikisini de kullanarak sayısal bir şekilde arttıracaktır çalıştık var=$var+1ve var=($var+1)başarılı olamadı. Değişken bir sayıdır, bash bir dize olarak okunuyor gibi görünmektedir.

Ubuntu 13.10’da Bash sürümü 4.2.45 (1) - yayın (x86_64-pc-linux-gnu).

Yanıtlar:


947

Bash'ta bir değişkeni arttırmanın birden fazla yolu var, ancak denediğiniz doğru değil.

Örneğin aritmetik genişleme kullanabilirsiniz :

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

Veya kullanabilirsiniz let:

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

Ayrıca bakınız: http://tldp.org/LDP/abs/html/dblparens.html .


31
veya ((++var))veya ((var=var+1))veya ((var+=1)).
gniourf_gniourf

6
Merakla, değil var=0; ((var++))iken bir hata kodu döndürür var=0; ((var++)); ((var++)). Neden bir fikrin var mı?
phunehehe

15
@phunehehe Şuna bak help '(('. Son satır diyor ki:Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise.
Radu Rădeanu

2
1@ Gniourf_gniourf'un bahşişinin neden içermediği ((++var))ancak olmadığına göre sıfırın değerlendirilmesinden şüpheleniyorum ((var++)).
DreadPirateShawn

4
let var++tırnak olmadan kullanmak güvenli midir?
wjandrea

160
var=$((var + 1))

Bash'deki aritmetik $((...))sözdizimini kullanır .


9
Kabul edilen cevaptan çok daha iyi. Sadece% 10'luk bir alanda, yeterli sayıda örnek vermeyi başardınız (biri bol - dokuz sadece gösteriş yaptığınız noktaya göre saygısız) ve bize bunun ((...))aritmetik kullanmanın anahtarı olduğunu bilecek kadar bilgi sağladınız bash Sadece kabul edilen cevaba bakmanın farkında değildim - operasyonların sırası ya da kabul edilen cevabın bütün parantezlerine yol açan bir şeyler hakkında garip kurallar olduğunu düşünmüştüm.
ArtOfWarfare

82

Çeşitli seçeneklerin Performans Analizi

Radu Rădeanu'nun bash'ta bir değişkeni arttırmak için aşağıdaki yolları sağlayan cevabı sayesinde :

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

Başka yolları da var. Örneğin, bu sorudaki diğer cevaplara bakın.

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

Çok fazla seçeneğe sahip olmak şu iki soruya yol açar:

  1. Aralarında performans farkı var mı?
  2. Varsa hangisi en iyi performansı gösterir?

Artımlı performans testi kodu:

#!/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

Sonuçlar:

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

Sonuç:

Bash gerçekleştirerek en hızlı görünüyor i+=1zaman $ibir tamsayı olarak ilan edilir. letifadeler özellikle yavaş görünüyor ve expren yavaşı çünkü bir yerleşik değil.


Görünüşe göre hız komut uzunluğu ile ilişkilidir. Komutların aynı fonksiyonları mı çağırdığını merak ediyorum.
MatthewRock

18

Bu da var:

var=`expr $var + 1`

Alanların dikkatli not edin ve aynı zamanda ` değildir '

Radu'nun cevapları ve yorumları kapsamlı ve çok yararlı olsa da, bash'a özgü. Özellikle bash hakkında soru sorduğunuzu biliyorum, ama ben bu soruyu bulduğumdan beri aynı şeyi yapmaya çalışırken UCLinux altındaki busybox'ta sh kullanarak aynı şeyi yapacağımı düşündüm. Bu bash ötesinde taşınabilir.


1
Ayrıca kullanabilirsinizi=$((i+1))
wjandrea

Proses ikamesi $(...)bu kabukta mevcutsa, onu kullanmanızı öneririm.
Radon Rosborough


7

Bütün cevaplarda eksik olan bir yöntem var. bc

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

bcPOSIX standardı tarafından belirtilmiştir , bu nedenle Ubuntu ve POSIX uyumlu sistemlerin tüm sürümlerinde bulunmalıdır. <<<Yönlendirme için değişmiş olabilir echo "$VAR" | bctaşınabilirlik için, ama soru sorar beri bash- sadece kullanmak Tamam <<<.


6

Dönüş kodu 1sorunu tüm varsayılan varyantları (buyunca let, (())vs.). Bu genellikle, örneğin kullanılan komut dosyalarında sorun çıkarır set -o errexit. İşte 1değerlendiren matematik ifadelerindeki hata kodunu önlemek için kullanıyorum 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

0

Bu kadar basit bir görevi başarmanın en kötü yolu bu olsa da, sanırım sadece eğlenceyi belgelemek istedim (kod golfün tam tersi).

$ var=0
$ echo $var
0
$ var="$(python -c 'print('$var'+1)')"
$ echo $var
1

veya

$ var="$(printf '%s\n' $var'+1' | bc)"
$ echo $var
1

Burada diğer daha iyi seçeneklerden birini ciddi olarak kullanın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.