Melakukan matematika sederhana di baris perintah menggunakan fungsi bash: $ 1 dibagi dengan $ 2 (mungkin menggunakan bc)


33

Kadang-kadang saya perlu membagi satu nomor dengan yang lain. Akan lebih bagus jika saya bisa mendefinisikan fungsi bash untuk ini. Sejauh ini, saya terpaksa menggunakan ekspresi seperti

echo 'scale=25;65320/670' | bc

tetapi akan lebih bagus jika saya bisa mendefinisikan fungsi .bashrc yang terlihat seperti

divide () {
  bc -d $1 / $2
}

Jawaban:


45

Saya memiliki fungsi bash praktis bernama calc:

calc () {
    bc -l <<< "$@"
}

Contoh penggunaan:

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

Anda dapat mengubahnya sesuai keinginan Anda. Sebagai contoh:

divide() {
    bc -l <<< "$1/$2"
}

Catatan: <<< adalah string di sini yang dimasukkan ke dalam stdin dari bc. Anda tidak perlu memohon echo.


3
Saya setuju ini terlihat lebih baik tanpa tambahan gema yang dilemparkan, tetapi karena itu adalah shell builtin, ia datang dengan sedikit atau tanpa biaya tambahan. Apa yang membuat saya tidak menggunakan '<<<' dalam fungsi shell adalah keterbatasannya untuk bash, sementara gema tambahan memungkinkan menggunakannya di shell bourne asli atau ksh tanpa perubahan.
Tatjana Heuser

@TatjanaHeuser ksh, varian 93, mendukung string di sini.
Kusalananda

Untuk menetapkan ke variabel, saya melakukan ini: foo = $ (bc -l <<< "(2 * 5) + 5")
thebiggestlebowski

20

Bash dapat melakukan matematika itu sendiri sampai batas tertentu. Namun, ini tidak berguna untuk keakuratan.

[user]$ echo $(( 10/5 ))
2

Tapi Anda benar - fungsi bash akan menjadi jalan pintas sederhana dan contoh Anda pada dasarnya berfungsi.

divide() {
  echo "scale=25;$1/$2" | bc
}

Lemparkan ke dalam .bashrc Anda dan kemudian Anda dapat:

[user]$ divide 10 5
2.0000000000000000000000000

1
echo $((10 / 5))tidak perlu kutip.
pengguna tidak diketahui

1
Gangguan yang signifikan: echo $((6383/7671)) akan memberi Anda nol. Anda harus eksplisit tentang nomor floating point:echo $((6383.0/7671.0))
Sridhar Sarnobat

9

Anda mungkin tahu bash builtin 'expr' seperti pada

$ expr 60 / 5
12

yang terbatas pada bilangan bulat dan membutuhkan ruang di antara argumen.

Apa yang membuat Anda tidak mendefinisikan fungsi di sepanjang garis ekspresi gema yang sudah Anda gunakan? Yaitu

 divide () {
   echo $1/$2 | bc
 }

1
hanya ketidaktahuan. saya tidak menyadari bahwa saya bisa membuatnya bekerja seperti itu ...
ixtmixilix

7

Tidak benar-benar jawaban untuk pertanyaan yang tepat ini, tetapi mungkin baik untuk diketahui. Gunakan zsh;-)

% echo $((65320./670))
97.492537313432834

Saya sebenarnya mencari pertanyaan ini karena saya berganti ke zsh dan tidak bisa menggunakan bash's exprbuiltin, jawaban yang sangat bagus terlepas dari itu :)
Steen Schütt

2

Jika Anda telah calcmenginstal pada sistem Anda dan Anda tidak suka pembulatan, Anda dapat:

div() { calc "$1 / $2"; }

hmm ... tidak dapat menemukan paket debian untuk 'calc'
ixtmixilix

Paket ini disebut apcalc (Presisi Arbiter) ... Biner disebutcalc
Peter.O

@ Peter.O Ok, dalam repo Arch Linux namanya calc.

2

Retasan kotor untuk nilai-nilai kecil dan presisi terbatas tanpa menggunakan bc akan, untuk melipatgandakan nominator sebelum pembagian, untuk mendapatkan hasil yang akurat.

Contoh tanpa presisi:

echo $((13/7)) 
1

dan dengan presisi 2 digit: kalikan dengan 100 dan pindahkan titik desimal 2 langkah ke kiri:

echo $((100*13/7)) | sed 's/..$/.&/'
1.85
echo $((100*13/7))%
185%

Ini hanya berguna jika rentang angka diketahui sebelumnya, dan presisi selalu sama. Menghindari menelepon bc , dan menelepon sed sepertinya tidak masuk akal.

Perhatikan, bahwa mengalikan nilai mungkin menyebabkan kesalahan overflow, tetapi tidak terlalu awal:

echo $((1000000000*12345678901))
-6101065172709551616

Menggunakan tanda kurung ganda untuk mengevaluasi ekspresi matematika sudah usang. Gunakan: $[expression]sebagai gantinya
laebshade

3
@laebshade: Saya bisa membuktikan Anda salah, yang terjadi adalah sebaliknya. Berikut ini adalah kutipan dari manual bash:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
pengguna tidak diketahui

Juga dibahas di sini , di  sini  dan di  sini .
G-Man Mengatakan 'Reinstate Monica'

0

Alih-alih menggunakan bc, Anda bisa menggunakan awk:

div() { awk -v p=$1 -v q=$2 'BEGIN{print p/q}'; }

-4
echo Division
efgh=$num1/$num2
remainder=$num1%num2
echo $num1 "/" $num2 "=" $efgh.$remainder
echo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.