Bagaimana saya bisa melakukan pembagian dengan variabel di shell Linux?
143
Ketika saya menjalankan perintah di shell saya seperti di bawah ini, itu mengembalikan expr: non-integer argumentkesalahan. Bisakah seseorang menjelaskan hal ini kepada saya?
$ x=20
$ y=5
$ expr x / y
expr: non-integer argument
@ShivanRaptor Meskipun orang mungkin berpendapat bahwa pertanyaannya adalah pertanyaan RTFM, itu pasti pertanyaan pemrograman shell yang valid. Ini juga merupakan pertanyaan yang masuk akal bagi seseorang yang berasal dari bahasa yang tidak memerlukan dereferensi (mis. Ruby atau JavaScript). Ini harus dibiarkan terbuka.
Todd A. Jacobs
6
@ShivanRaptor Tidak, ini adalah topik di sini. Ini tentang pemrograman di Bash. Unix / Linux utamanya untuk menggunakan sistem, bukan pemrograman. Sekarang, skrip shell menjangkau batas antara pemrograman dan penggunaan sistem, jadi ini bisa menjadi topik di situs mana pun. Jika ada pertanyaan tentang "bagaimana cara menyiapkan jaringan", itu pasti akan menjadi milik Unix / Linux. Jika itu adalah pertanyaan tentang keybindings interaktif di Bash, itu juga termasuk di sana. Tapi pertanyaan tentang skrip shell pasti menjadi topik di sini dan juga di sana.
Brian Campbell
Lihat jawaban saya di sini, yang menggambarkan pengurangan dan pembagian variabel $ BASH, menggunakan panggilan ke Python dari shell (untuk mengubah int menjadi float ...): stackoverflow.com/questions/8385627/…
Victoria Stuart
Jawaban:
203
Variabel tersebut adalah variabel shell. Untuk mengembangkannya sebagai parameter ke program lain ( yaituexpr ), Anda perlu menggunakan $awalan:
expr $x / $y
Alasan yang dikeluhkan adalah karena Anda mengira Anda mencoba menggunakan karakter alfabetis ( yaitu non-integer)
Jika Anda menggunakan Bash shell, Anda dapat memperoleh hasil yang sama menggunakan sintaks ekspresi:
Mengapa tidak menggunakan let; Saya merasa jauh lebih mudah. Berikut adalah contoh yang mungkin berguna bagi Anda:
start=`date +%s`
# ... do something that takes a while ...
sleep 71
end=`date +%s`
let deltatime=end-start
let hours=deltatime/3600
let minutes=(deltatime/60)%60
let seconds=deltatime%60
printf"Time spent: %d:%02d:%02d\n"$hours$minutes$seconds
Contoh sederhana lainnya - hitung jumlah hari sejak 1970:
Mereferensikan Variabel Bash Memerlukan Perluasan Parameter
Shell default di sebagian besar distribusi Linux adalah Bash. Di Bash, variabel harus menggunakan awalan tanda dolar untuk perluasan parameter . Sebagai contoh:
x=20
y=5
expr $x / $y
Tentu saja, Bash juga memiliki operator aritmatika dan sintaks ekspansi aritmatika khusus , jadi tidak perlu memanggil biner expr sebagai proses terpisah. Anda dapat membiarkan shell melakukan semua pekerjaan seperti ini:
Ini tidak ada hubungannya dengan dereferensi tetapi interpolasi dan exprtidak disarankan pada tahun 2013.
Gilles Quenot
@sputnick Anda jelas bingung. Silakan berkonsultasi dengan kamus. Lihat dereferensi dan interpolasi .
Todd A. Jacobs
1
Kata yang lebih baik berkembang , tetapi tidak dereferensi . dereferencing digunakan saat kita menggunakan pointer , tidak demikian halnya di sini, itu hanya variabel sederhana.
Gilles Quenot
1
@Prashant: tldp tidak dikenal sebagai referensi yang baik di dunia bash.
Gilles Quenot
2
Untuk mendapatkan angka setelah koma desimal, Anda dapat melakukan ini: -
read num1 num2
div=`echo$num1 / $num2 | bc -l`
echo$div
ini akan bekerja dengan baik. Tetapi jika Anda ingin menggunakan / operator dalam pernyataan kasus daripada tidak dapat menyelesaikannya.
Dalam hal ini gunakan string sederhana seperti div atau devide atau yang lainnya. Lihat kodenya
Ini salah. /berfungsi dengan baik sebagai label shell-case. Apa yang tidak berhasil adalah menggunakan *perkalian tanpa mengutipnya, yang mungkin memang seperti yang Anda lakukan; yang menyebabkannya secara efektif menimpa semua item berikut dalam kasus ini, yang dalam contoh Anda adalah 'devide' dan 'modulo'
Jawaban:
Variabel tersebut adalah variabel shell. Untuk mengembangkannya sebagai parameter ke program lain ( yaitu
expr
), Anda perlu menggunakan$
awalan:expr $x / $y
Alasan yang dikeluhkan adalah karena Anda mengira Anda mencoba menggunakan karakter alfabetis ( yaitu non-integer)
Jika Anda menggunakan Bash shell, Anda dapat memperoleh hasil yang sama menggunakan sintaks ekspresi:
echo $((x / y))
Atau:
z=$((x / y)) echo $z
sumber
man bash
pada prompt (q
untuk keluar)Saya yakin itu sudah disebutkan di utas lain:
calc(){ awk "BEGIN { print "$*" }"; }
maka Anda cukup mengetik:
Dalam kasus Anda, ini akan menjadi:
x=20; y=3; calc $x/$y
atau jika Anda lebih suka, tambahkan ini sebagai skrip terpisah dan buat tersedia di $ PATH sehingga Anda akan selalu memilikinya di shell lokal Anda:
#!/bin/bash calc(){ awk "BEGIN { print $* }"; }
sumber
echo '1 / 3' | bc -l
Mengapa tidak menggunakan let; Saya merasa jauh lebih mudah. Berikut adalah contoh yang mungkin berguna bagi Anda:
start=`date +%s` # ... do something that takes a while ... sleep 71 end=`date +%s` let deltatime=end-start let hours=deltatime/3600 let minutes=(deltatime/60)%60 let seconds=deltatime%60 printf "Time spent: %d:%02d:%02d\n" $hours $minutes $seconds
Contoh sederhana lainnya - hitung jumlah hari sejak 1970:
let days=$(date +%s)/86400
sumber
Mereferensikan Variabel Bash Memerlukan Perluasan Parameter
Shell default di sebagian besar distribusi Linux adalah Bash. Di Bash, variabel harus menggunakan awalan tanda dolar untuk perluasan parameter . Sebagai contoh:
x=20 y=5 expr $x / $y
Tentu saja, Bash juga memiliki operator aritmatika dan sintaks ekspansi aritmatika khusus , jadi tidak perlu memanggil biner expr sebagai proses terpisah. Anda dapat membiarkan shell melakukan semua pekerjaan seperti ini:
x=20; y=5 echo $((x / y))
sumber
expr
tidak disarankan pada tahun 2013.Untuk mendapatkan angka setelah koma desimal, Anda dapat melakukan ini: -
read num1 num2 div=`echo $num1 / $num2 | bc -l` echo $div
sumber
anggap saja
kemudian
ini akan bekerja dengan baik. Tetapi jika Anda ingin menggunakan / operator dalam pernyataan kasus daripada tidak dapat menyelesaikannya. Dalam hal ini gunakan string sederhana seperti div atau devide atau yang lainnya. Lihat kodenya
sumber
/
berfungsi dengan baik sebagai label shell-case. Apa yang tidak berhasil adalah menggunakan*
perkalian tanpa mengutipnya, yang mungkin memang seperti yang Anda lakukan; yang menyebabkannya secara efektif menimpa semua item berikut dalam kasus ini, yang dalam contoh Anda adalah 'devide' dan 'modulo'