Cố gắng tìm ra cách chuyển đổi một đối số thành một số nguyên để thực hiện số học trên, sau đó in ra, nói addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Cố gắng tìm ra cách chuyển đổi một đối số thành một số nguyên để thực hiện số học trên, sau đó in ra, nói addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Câu trả lời:
Trong bash, người ta không "chuyển đổi một đối số thành một số nguyên để thực hiện số học". Trong bash, các biến được coi là số nguyên hoặc chuỗi tùy thuộc vào ngữ cảnh.
Để thực hiện số học, bạn nên gọi toán tử mở rộng số học $((...))
. Ví dụ:
$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3
hoặc thường được ưa thích:
$ echo "$((a + 1))"
3
Bạn nên lưu ý rằng bash (trái ngược với ksh93, zsh hoặc yash) chỉ thực hiện số học số nguyên . Nếu bạn có số dấu phẩy động (số có số thập phân), thì có các công cụ khác để hỗ trợ. Ví dụ bc
: sử dụng :
$ b=3.14
$ echo "$(($b + 1))"
bash: 3.14 + 1: syntax error: invalid arithmetic operator (error token is ".14 + 1")
$ echo "$b + 1" | bc -l
4.14
Hoặc bạn có thể sử dụng hệ vỏ với hỗ trợ số học dấu phẩy động thay vì bash:
zsh> echo $((3.14 + 1))
4.14
Trong bash
, bạn có thể thực hiện chuyển đổi từ bất cứ thứ gì sang số nguyên bằng printf -v :
printf -v int '%d\n' "$1" 2>/dev/null
Số nổi sẽ được chuyển đổi thành số nguyên, trong khi mọi thứ không giống như số sẽ được chuyển đổi thành 0. Số mũ sẽ được cắt thành số trước e
Thí dụ:
$ printf -v int '%d\n' 123.123 2>/dev/null
$ printf '%d\n' "$int"
123
$ printf -v int '%d\n' abc 2>/dev/null
$ printf '%d\n' "$int"
0
$ printf -v int '%d\n' 1e10 2>/dev/null
$ printf '%d\n' "$int"
1
printf -v
điều này có thể đạt được với sự thay thế lệnh:int="$(printf '%d' 123.123 2>/dev/null)"
bash
sử dụng phiên bản nào?
Một tình huống tương tự đã xuất hiện gần đây khi phát triển các tập lệnh bash để chạy trong cả môi trường Linux và OSX. Kết quả của một lệnh trong OSX đã trả về một chuỗi chứa mã kết quả; ví dụ " 0"
. Tất nhiên, điều này không thể kiểm tra chính xác trong trường hợp sau:
if [[ $targetCnt != 0 ]]; then...
Giải pháp là buộc (tức là 'chuyển đổi') kết quả thành một số nguyên, tương tự như những gì @ John1024 đã trả lời ở trên để nó hoạt động như mong đợi:
targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
==
vv trong [[
(cũng [
aka test
) làm so sánh chuỗi. Có các toán tử khác nhau để so sánh số học, ví dụ [[ $targetcnt -ne 0 ]]
; xem manpage (hoặc thông tin) dưới Biểu thức có điều kiện. Để cắt các không gian cụ thể, bạn có thể sử dụng [
với mở rộng biến không được trích dẫn [ $targetcnt == 0 ]
để có được các từ mặc định (KHÔNG được thực hiện [[
) nhưng nói chung cách tiếp cận đó dẫn bạn đến nguy hiểm.
quan tâm đến mã màu, ngay cả trong dấu vết ( -x
) chúng sẽ không xuất hiện, điều sẽ cho đi là chuỗi được cho là một số được gói trong dấu ngoặc kép cho dù bạn in nó như thế nào.
$((var+var))
không thành công mặc dù nếu bạn echo
hoặc printf
cả hai vars họ giống nhau. Tôi không biết cách khắc phục vì tôi chỉ có thể sửa nó bằng cách vô hiệu hóa mã màu ở nguồn đầu ra. Để phát hiện nó trong các dấu vết các bản ghi bạn sẽ thấy những biến vi phạm giao như var='0'
trong khi nó chỉ đơn giản nênvar=0
sed
nếu bạn không thể vô hiệu hóa nó
printf "1 + %s\n" $1 won't do ?