Bagaimana cara menambah variabel di bash?

Saya telah mencoba menambah variabel numerik menggunakan keduanya var=$var+1 dan var=($var+1) tanpa keberhasilan. Variabelnya adalah angka, meskipun bash tampaknya membacanya sebagai string.

Bash versi 4.2.45 (1)-rilis (x86_64-pc-linux-gnu) di Ubuntu 13.10.

Ada lebih dari satu cara untuk menambah variabel di bash, tetapi apa yang anda coba tidak benar.

Anda dapat menggunakan misalnya ekspansi aritmatika:

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

Atau Anda dapat menggunakan let:

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

Lihat juga: http://tldp.org/LDP/abs/html/dblparens.html.

var=$((var + 1))

Aritmatika dalam bash menggunakan $((...)) sintaksis.

Berbagai pilihan untuk kenaikan sebesar 1, dan analisis kinerja

Berkat Jawaban Radu R Molibdeanu itu menyediakan cara berikut untuk menambah variabel di bash:

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

Ada cara lain juga. Misalnya, lihat jawaban lain pada pertanyaan ini.

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

Memiliki begitu banyak pilihan mengarah ke dua pertanyaan ini:

  1. Apakah ada perbedaan kinerja di antara mereka?
  2. Jika demikian, mana yang berkinerja terbaik?

Kode uji kinerja tambahan:

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

Hasil:

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

Kesimpulan:

Tampaknya bash tercepat dalam melakukan i+=1 kapan $i dinyatakan sebagai bilangan bulat. let pernyataan tampaknya sangat lambat, dan expr adalah jauh paling lambat karena tidak dibangun ke bash.

Ada juga ini:

var=`expr $var + 1`

Perhatikan baik-baik ruang dan juga ` tidak '

Sementara jawaban Radu, dan komentarnya, sangat lengkap dan sangat membantu, mereka spesifik bash. Saya tahu Anda secara khusus bertanya tentang bash, tetapi saya pikir saya akan masuk karena saya menemukan pertanyaan ini ketika saya ingin melakukan hal yang sama menggunakan sh di busybox di bawah uCLinux. Ini portabel luar bash.

Jika Anda menyatakan $var sebagai bilangan bulat, maka apa yang anda coba pertama kali akan benar-benar berfungsi:

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

Referensi: Jenis variabel, panduan Bash untuk pemula

Ada satu metode yang hilang dalam semua jawaban - bc

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

bc ditentukan oleh POSIX standar, jadi harus ada pada semua versi Ubuntu dan sistem yang sesuai dengan POSIX. The <<< pengalihan dapat diubah menjadi echo "$VAR" | bc untuk portabilitas, tapi karena pertanyaan bertanya tentang bash - tidak apa-apa untuk hanya menggunakan <<<.

Kode kembali 1 masalah hadir untuk semua varian default (let, (()), dll.). Ini sering menyebabkan masalah, misalnya, dalam skrip yang menggunakan set -o errexit. Inilah yang saya gunakan untuk mencegah kode kesalahan 1 dari ekspresi matematika yang mengevaluasi ke 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

Ini harus menjadi cara terburuk untuk menyelesaikan tugas yang begitu sederhana tetapi saya hanya ingin mendokumentasikannya untuk bersenang-senang, saya kira (kebalikan dari code golf).

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

atau

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

Serius menggunakan salah satu pilihan lain yang jauh lebih baik di sini.

Ini adalah taruhan yang aman

(( var = var + 1 ))

Jika nilai yang dihasilkan bukan nol, maka pengaturan exit on error akan menghentikan skrip Anda

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