bagaimana saya bisa menambahkan (kurangi, dll.) dua angka dengan bash?

90

Saya dapat membaca angka dan operasinya dengan:

echo "First number please"
read num1
echo "Second number please"
read num2
echo "Operation?"
read op

tapi kemudian semua upaya saya untuk menambahkan angka gagal:

case "$op" in
  "+")
    echo num1+num2;;
  "-")
    echo `num1-num2`;;
esac

Lari:

First number please
1
Second mumber please
2
Operation?
+

Keluaran:

num1+num2

...atau...

echo $num1+$num2;;

# results in: 1+2    

...atau...

echo `$num1`+`$num2`;;

# results in: ...line 9: 1: command not found

Sepertinya saya mendapatkan string masih mungkin ketika saya mencoba menambahkan add ("2 + 2" bukannya "4").

Michael Durrant
sumber
5
Saya mengedit judul Anda karena ini adalah pertanyaan umum yang bagus, dan jika Anda mempersempit konteksnya, Anda akan menyadari bahwa ini tidak ada hubungannya dengan caseatau apa pun kecuali satu baris:, echo $num+$numkarena itu akan mereproduksi masalah dengan tepat . Gagasan dengan meminimalkan konteks dalam pertanyaan pemrograman dijelaskan di sini: sscce.org
goldilocks
2
+1 Hai goldilocks, ya itu menjadi jelas bagi saya setelahnya, tapi ya saya sepenuhnya setuju dengan alur pemikiran Anda dan ya, semakin spesifik dan 'tunggal' pertanyaan adalah semakin baik. Saya menyambut hasil edit Anda :) Terima kasih :)
Michael Durrant

Jawaban:

117

Aritmatika dalam kulit POSIX dilakukan dengan $dan tanda kurung ganda (( )):

echo "$(($num1+$num2))"

Anda dapat menetapkan dari itu echo:

num1="$(($num1+$num2))"

Ada juga expr:

expr $num1 + $num2

Dalam skrip $(())lebih disukai karena menghindari garpu / eksekusi untuk exprperintah.

goldilocks
sumber
Atau bahkan langsung echo $(($num1$op$num2))tanpa melibatkan case.
manatwork
Tidak ada yang caseterlibat di sini.
goldilocks
1
Tidak, tetapi Anda menggunakan literal +, jadi perlu bagian caseluar untuk menangani pengurangan secara terpisah.
manatwork
1
@manatwork: Maksud Anda menghilangkan casedari kode OP dengan echo $(($num1$op$num2))- yang akan berfungsi, tetapi menggunakan caselebih kuat karena Anda dapat menangani kesalahan dengan default *.
goldilocks
+1 untuk Anda berdua. Saya menggunakan case (mungkin tidak menunjukkannya di awal) tetapi ketika Anda berdua menyadari masalahnya bukan tentang case.
Michael Durrant
13

Jawaban yang ada adalah bash murni, jadi akan lebih cepat dari ini, tetapi hanya bisa menangani bilangan bulat. Jika Anda perlu menangani pelampung, Anda harus menggunakan program eksternal bc.

$ echo 'scale=4;3.1415+9.99' | bc
13.1315

Ia scale=4meminta bcagar menggunakan empat tempat desimal. Lihat man bcuntuk informasi lebih lanjut.

Evilsoup
sumber
Catatan sementara yang bashtidak mendukung floating point aritmatika dengan $((...)), banyak kerang ( ksh93, zsh, yashsetidaknya) lakukan. Keuntungannya bcadalah ia mendukung presisi sembarang sementara aritmatika shell terbatas pada jenis prosesor double. Perhatikan bahwa Anda tidak perlu mengatur di scalesini. Untuk tambahan, scaleparameter tidak digunakan. Skala 3.1415+9.99akan diturunkan dari operan (di sini 4).
Stéphane Chazelas
Bagaimana cara menghitung jika satu nilai bernilai 450dan yang lainnya adalah desimal disimpan pada variabel $mynumber? Sebagai contoh 450-$mynumber,.
Sigur
@sigur echo "450-$mynumber" | bcharus melakukannya. Jika Anda ingin variabel berkembang, Anda harus menggunakan tanda kutip ganda daripada tanda kutip tunggal.
evilsoup
@ evilsoup, sekarang berfungsi seperti pesona. Terima kasih.
Sigur
computedval=$(echo 'scale=10;var1-var2' | bc)tidak bekerja, juga tidakcomputedval=$(echo 'scale=10;$var1-$var2' | bc)
StatsSorceress
5
echo `expr $a + $b`   
echo `expr $a - $b`   
echo `expr $a \* $b`   
echo `expr $a / $b`   

Perhatikan \sebelum *(untuk perkalian), seluruh ekspresi harus berada dalam tanda kutip `.

Himani
sumber
1
exprtidak perlu, dan tidak pernah perlu untuk menangkap output standar dari sebuah perintah hanya untuk menuliskannya kembali ke output standar.
chepner
2

minimalis

total=0
((total+=qty))
geekzspot
sumber
1

Anda juga dapat menggunakan $[ ... ]struktur. Dalam hal ini, kami menggunakan mechanizm bawaan di Bash, yang lebih cepat dan sedikit lebih nyaman digunakan. Karena kita tahu bahwa segala sesuatu di antara $ [, dan] diperlakukan sebagai ekspresi, kita tidak perlu mendahului variabel dengan $. Demikian pula, kita tidak perlu merasa aman *dari memperlakukannya seperti sebuah pola.

num1=2
num2=3
echo $[num1 + num2]
5
jedi
sumber
0

Berdasarkan urutan input yang Anda minta dari pengguna, tampaknya Anda menggunakan notasi polish terbalik.

echo "First number please"
read num1
echo "Second number please"
read num2
echo "Operation?"
read op

Anda dapat melakukannya lebih baik hanya dengan menggunakan dc(kalkulator meja) secara langsung, karena memang itulah tujuannya.

DESCRIPTION
       Dc is a reverse-polish desk calculator which supports unlimited pre-
       cision arithmetic.

Sesi contoh menggunakan dc:

$ dc
1 2 + p    # This part is typed; the result comes next.
3
q  # This is also typed.
$

Atau, non-interaktif:

$ dc -e '1 2 + p'
3
$
Wildcard
sumber