Làm toán đơn giản trên dòng lệnh bằng các hàm bash: $ 1 chia cho $ 2 (có thể sử dụng bc)


33

Đôi khi tôi cần chia một số cho một số khác. Sẽ thật tuyệt nếu tôi chỉ có thể định nghĩa hàm bash cho việc này. Cho đến nay, tôi buộc phải sử dụng các biểu thức như

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

nhưng thật tuyệt nếu tôi có thể định nghĩa hàm .bashrc trông giống như

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

Câu trả lời:


45

Tôi có một chức năng bash tiện dụng được gọi là calc:

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

Ví dụ sử dụng:

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

Bạn có thể thay đổi điều này cho phù hợp với chính mình. Ví dụ:

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

Lưu ý: <<< là một chuỗi ở đây được đưa vào stdin của bc. Bạn không cần phải gọi echo.


3
Tôi đồng ý rằng nó trông tốt hơn mà không có tiếng vang bổ sung, nhưng vì nó được tích hợp sẵn, nên nó đi kèm với ít hoặc không mất thêm chi phí. Điều khiến tôi không sử dụng '<<<' trong các hàm shell là giới hạn của nó đối với bash, trong khi tiếng vang bổ sung cho phép sử dụng nó trong vỏ bourne ban đầu hoặc ksh mà không thay đổi.
Tatjana Heuser

@TatjanaHeuser ksh, biến thể 93, hỗ trợ chuỗi ở đây.
Kusalananda

Để gán cho một biến, tôi đã làm điều này: foo = $ (bc -l <<< "(2 * 5) + 5")
thebiggestlebowski

20

Bash có thể tự làm toán ở một mức độ nào đó. Nó không hữu ích cho độ chính xác, mặc dù, nó làm tròn.

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

Nhưng bạn hoàn toàn đúng - một hàm bash sẽ là một phím tắt đơn giản và về cơ bản ví dụ của bạn hoạt động.

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

Ném nó vào .bashrc của bạn và sau đó bạn có thể:

[user]$ divide 10 5
2.0000000000000000000000000

1
echo $((10 / 5))không cần báo giá.
người dùng không xác định

1
Khó chịu đáng kể: echo $((6383/7671)) sẽ cho bạn số không. Bạn cần phải rõ ràng về số dấu phẩy động:echo $((6383.0/7671.0))
Sridhar Sarnobat

9

Bạn có thể biết bash dựng sẵn 'expr' như trong

$ expr 60 / 5
12

được giới hạn trong số nguyên và cần khoảng trắng giữa các đối số.

Điều gì ngăn bạn xác định một chức năng dọc theo các dòng của biểu thức tiếng vang bạn đang sử dụng? I E

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

1
chỉ vô minh. tôi đã không nhận ra rằng tôi có thể làm cho nó hoạt động theo cách đó ...
ixtmixilix

7

Không thực sự là một câu trả lời cho câu hỏi chính xác này, nhưng nó có thể là tốt để biết. Sử dụng zsh;-)

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

Tôi thực sự đang tìm kiếm câu hỏi này vì tôi đã đổi thành zsh và không thể sử dụng exprnội dung của bash , vì vậy câu trả lời tốt bất kể :)
Steen Schütt

2

Nếu bạn đã calccài đặt trên hệ thống của mình và bạn không thích làm tròn, bạn có thể:

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

hmm ... không thể tìm thấy bất kỳ gói debian nào cho 'calc'
ixtmixilix

Gói được gọi là apcalc (Chính xác tùy ý) ... Nhị phân được gọi làcalc
Peter.O

@ Peter.O Ok, trong bản phát hành Arch Linux, nó được gọi calc.

2

Một hack bẩn cho các giá trị nhỏ và độ chính xác hạn chế mà không sử dụng bc sẽ là, để nhân lên người đề cử trước khi phân chia, để có được kết quả chính xác.

Ví dụ không chính xác:

echo $((13/7)) 
1

và với độ chính xác 2 chữ số: nhân với 100 và di chuyển dấu thập phân 2 bước sang trái:

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

Điều này chỉ hữu ích nếu phạm vi số được biết trước và độ chính xác luôn giống nhau. Tránh gọi bc , và gọi sed có vẻ không hợp lý lắm.

Lưu ý, việc nhân các giá trị có thể dẫn đến lỗi tràn, nhưng không sớm:

echo $((1000000000*12345678901))
-6101065172709551616

Sử dụng dấu ngoặc đơn để đánh giá các biểu thức toán học không được dùng nữa. Sử dụng: $[expression]thay vào đó
laebshade

3
@laebshade: Tôi có thể chứng minh bạn sai, điều ngược lại là đúng. Dưới đây là một trích dẫn của hướng dẫn bash:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
người dùng không xác định

Cũng thảo luận ở đây ,  ở đây  và  ở đây .
G-Man nói 'Phục hồi Monica'

0

Thay vì sử dụng bc, bạn có thể sử dụng 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.