Làm thế nào tôi có thể phân chia với các biến trong một vỏ Linux?


136

Khi tôi chạy các lệnh trong shell của mình như bên dưới, nó sẽ trả về một expr: non-integer argumentlỗi. Có ai đó giải thích điều này cho tôi biết không?

$ x=20
$ y=5
$ expr x / y 
expr: non-integer argument

4
@ShivanRaptor Mặc dù người ta có thể lập luận rằng câu hỏi là câu hỏi RTFM, nhưng đây chắc chắn là một câu hỏi lập trình shell hợp lệ. Đây cũng là một câu hỏi hợp lý cho ai đó đến từ các ngôn ngữ không yêu cầu hội thảo (ví dụ: Ruby hoặc JavaScript). Nó nên được để mở.
Todd A. Jacobs

6
@ShivanRaptor Không, đây là chủ đề ở đây. Đó là về lập trình ở Bash. Unix / Linux chủ yếu để sử dụng hệ thống, không phải lập trình. Bây giờ, shell scripting vượt qua ranh giới giữa lập trình và sử dụng hệ thống, vì vậy điều này có thể là về chủ đề trên một trong hai trang web. Nếu có một câu hỏi về "làm cách nào để thiết lập mạng", thì đó chắc chắn sẽ thuộc về Unix / Linux. Nếu đó là một câu hỏi về keybindings tương tác trong Bash, thì nó cũng sẽ thuộc về nó. Nhưng một câu hỏi về kịch bản shell chắc chắn là về chủ đề ở đây cũng như ở đó.
Brian Campbell

Xem câu trả lời của tôi ở đây, minh họa cho phép trừ và chia biến $ BASH, sử dụng lệnh gọi Python từ shell (để chuyển đổi int thành float ...): stackoverflow.com/questions/8385627/iêu
Victoria Stuart

Câu trả lời:


195

Các biến đó là biến shell. Để mở rộng chúng làm tham số cho chương trình khác ( tức là expr ), bạn cần sử dụng $tiền tố:

expr $x / $y

Lý do nó phàn nàn là vì nó nghĩ rằng bạn đang cố gắng hoạt động trên các ký tự chữ cái ( nghĩa là không nguyên)

Nếu bạn đang sử dụng shell Bash, bạn có thể đạt được kết quả tương tự bằng cú pháp biểu thức:

echo $((x / y))

Hoặc là:

z=$((x / y))
echo $z

1
Bạn có thể tìm hiểu rất nhiều bằng cách đọc qua trang man cho bash. Nhập man bashtại dấu nhắc ( qđể thoát)
thóc

62
Điều cần lưu ý ở đâu đó trên trang này là hầu hết (nếu không phải tất cả) các vỏ GNU / Linux chỉ thực hiện các hoạt động số nguyên .
Skippy le Grand Gourou

35

Tôi tin rằng nó đã được đề cập trong các chủ đề khác:

calc(){ awk "BEGIN { print "$*" }"; }

sau đó bạn có thể chỉ cần gõ:

calc 7.5/3.2
  2.34375

Trong trường hợp của bạn, nó sẽ là:

x=20; y=3;
calc $x/$y

hoặc nếu bạn thích, hãy thêm tập lệnh này dưới dạng một tập lệnh riêng biệt và làm cho nó có sẵn trong $ PATH để bạn sẽ luôn có nó trong trình bao cục bộ của mình:

#!/bin/bash
calc(){ awk "BEGIN { print $* }"; }

4
Bạn cũng có thể sử dụngecho '1 / 3' | bc -l
Eugene

19

Tại sao không dùng let; Tôi thấy nó dễ dàng hơn nhiều. Đây là một ví dụ bạn có thể thấy hữu ích:

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

Một ví dụ đơn giản khác - tính số ngày kể từ năm 1970:

let days=$(date +%s)/86400

15

Tham chiếu biến Bash yêu cầu mở rộng tham số

Shell mặc định trên hầu hết các bản phân phối Linux là Bash. Trong Bash, các biến phải sử dụng tiền tố ký hiệu đô la để mở rộng tham số . Ví dụ:

x=20
y=5
expr $x / $y

Tất nhiên, Bash cũng có các toán tử số họccú pháp mở rộng số học đặc biệt , do đó không cần phải gọi nhị phân expr như một quy trình riêng biệt. Bạn có thể để shell thực hiện tất cả các công việc như thế này:

x=20; y=5
echo $((x / y))

Xem Mở rộng số họcSố học Shell trong Hướng dẫn tham khảo Bash để biết tất cả các chi tiết chính.
Todd A. Jacobs

1
Này không có gì để làm với dereferencing nhưng nội suyexprkhông được khuyến khích trong năm 2013.
Gilles Quenot

@sputnick Bạn rõ ràng bối rối. Xin vui lòng tham khảo từ điển. Xem dereferenceNội suy .
Todd A. Jacobs

1
Một từ tốt hơn là mở rộng , nhưng không dereferencing . hội nghị được sử dụng khi chúng ta sử dụng con trỏ , đó không phải là trường hợp ở đây, đó chỉ là các biến đơn giản.
Gilles Quenot

1
@Prashant: tldp không được biết đến là một tài liệu tham khảo tốt trong thế giới bash.
Gilles Quenot

1

Giả sử

x=50
y=5

sau đó

z=$((x/y))

Điều này sẽ hoạt động đúng. Nhưng nếu bạn muốn sử dụng / toán tử trong các câu lệnh tình huống thì nó không thể giải quyết nó. nhập mã vào đây Trong trường hợp đó, sử dụng các chuỗi đơn giản như div hoặc devide hoặc một cái gì đó khác. Xem mã


Cái này sai. /hoạt động tốt như một nhãn vỏ. Những gì không hoạt động là sử dụng *để nhân lên mà không trích dẫn nó, đó có thể là những gì bạn thực sự đã làm; nguyên nhân nó để ghi đè lên một cách hiệu quả tất cả các mục sau đây trong trường hợp, mà trong ví dụ của bạn là 'chia' và 'modulo'
dave_thompson_085

0

Để lấy số sau dấu thập phân, bạn có thể làm điều này: -

read num1 num2
div=`echo $num1 / $num2 |bc -l`
echo $div
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.