Bash'deki bir değişken nasıl artırılır?

Her ikisini de kullanarak sayısal bir değişkeni artırmaya çalıştım var=$var+1 ve var=($var+1) başarı olmadan. Değişken bir sayıdır, ancak bash onu bir dize olarak okuyor gibi görünmektedir.

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

Bash'de bir değişkeni artırmanın birden fazla yolu vardır, ancak denedikleriniz doğru değildir.

Örneğin kullanabilirsiniz aritmetik genişleme:

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.

var=$((var + 1))

Bash kullanımlarında aritmetik $((...)) sözdizimi.

1 Artırmak için çeşitli seçenekler ve performans analizi

Sayesinde Radu Rădeanu'nun cevabı bu, bash'deki bir değişkeni artırmak için aşağıdaki yolları sağlar:

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

Başka yöntemler de vardır. Örneğin, bu sorunun diğer cevaplarına bakın.

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

Bu kadar çok seçeneğe sahip olmak bu iki soruya yol açar:

  1. Aralarında bir performans farkı var mı?
  2. Eğer öyleyse, hangisi en iyi sonucu verir?

Artımlı performans test 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=100000while ((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)'donefor 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.992si=$((i++))              user    0m0.964s((i=i+1))               user    0m0.760s((i+=1))                user    0m0.700s((i++))                 user    0m0.644s((++i))                 user    0m0.556slet "i=i+1"             user    0m1.116slet "i+=1"              user    0m1.100slet "i++"               user    0m1.008slet i=i+1               user    0m0.952slet i+=1                user    0m1.040slet i++                 user    0m0.820sdeclare -i i; i=i+1     user    0m0.528sdeclare -i i; i+=1      user    0m0.492si=0; i=$(expr $i + 1)   user    0m5.464s

Sonuç:

Görünüşe göre bash en hızlı performans sergiliyor i+=1 ne zaman $i tamsayı olarak bildirilir. let ifadeler özellikle yavaş görünüyor ve expr bu kesinlikle en yavaş olanıdır, çünkü yerleşik bir bash değildir.

Bir de bu var :

var=`expr $var + 1`

Boşluklara dikkat edin ve ayrıca ` değil '

Radu'nun cevapları ve yorumları kapsamlı ve çok yardımcı olsa da, bash'a özgüdür. Özellikle bash hakkında soru sorduğunuzu biliyorum, ancak uCLinux altında busybox'ta sh kullanarak aynı şeyi yapmak istediğimde bu soruyu bulduğumdan beri içeri gireceğimi düşündüm. Bu taşınabilir bash'ın ötesinde.

Eğer beyan edersen $var bir tamsayı olarak, ilk kez denediğiniz şey gerçekten işe yarayacaktır:

$ declare -i var=5$ echo $var5$ var=$var+1$ echo $var6

Referans: Değişken türleri, Yeni Başlayanlar için Bash Kılavuzu

Tüm cevaplarda eksik olan bir yöntem var - bc

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

bc tarafından belirtilir POSIX standart, bu nedenle Ubuntu ve POSIX uyumlu sistemlerin tüm sürümlerinde bulunmalıdır. Bu <<< yeniden yönlendirme şu şekilde değiştirilebilir echo "$VAR" | bc taşınabilirlik için, ancak soru sorulduğu için bash - sadece kullanmak sorun değil. <<<.

Dönüş kodu 1 tüm varsayılan varyantlar için sorun var (let, (()) vb.). Bu genellikle, örneğin, kullanan komut dosyalarında sorunlara neden olur set -o errexit. Hata kodunu önlemek için kullandığım şey şu 1 değerlendiren matematik ifadelerinden 0;

math() { (( "$@" )) || true; }math a = 10, b = 10math a++, b+=2math c = a + bmath mod = c % 20echo $a $b $c $mod#11 12 23 3

Bu kadar basit bir görevi yerine getirmenin en kötü yolu olmalı, ama sadece eğlenmek için belgelemek istedim (kod golfünün tam tersi).

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

veya

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

Cidden, buradaki diğer çok daha iyi seçeneklerden birini kullanın.

Bu güvenli bahis.

(( var = var + 1 ))

Elde edilen değer sıfır değilse, exit on error ayarı komut dosyanızı durduracaktır

set -evar=0(( var++ ))echo You will never get here