2013-03-05 33 views
23

Tôi muốn so sánh biến số dấu phẩy động với một số nguyên. Tôi biết điều này không phải là tốt nhất để làm với bash, nhưng toàn bộ kịch bản của tôi đã được viết bằng bash. Số $ có thể là số nguyên bất kỳ. Nếu nó dưới hoặc bằng 50, tôi muốn output1, cho tất cả những người khác tôi muốn có đầu ra với biến k khác. Đây là những gì tôi có cho đến thời điểm này:So sánh dấu chấm động với biến trong bash

number=43 
test=$(echo "scale=2; $number/50" | bc -l) 
echo "$test" 
for k in {1..5} 
do 
    if ["$test" -le 1] 
    then echo "output" 

    elif ["$test" -gt $k] 
    then echo "output$k" 
    fi 
done 

Nếu tôi thử với test = 0.43, vòng lặp đầu tiên thậm chí không hoạt động. Tôi nghĩ rằng nó đã làm với một số nguyên và một so sánh điểm nổi nhưng không thể làm cho nó hoạt động.

Mọi thứ tôi bị thiếu?

PS: điều này [0.43: command not found là thiết bị đầu cuối đầu ra.

+0

bạn cũng có thể chỉ cần chuyển sang ksh và sử dụng typeset để tự động tròn. (có sẵn từ năm 1993, hoạt động tốt) –

Trả lời

43

Bash không thể xử lý nổi. Ống để bc thay vì:

if [ $(echo " $test > $k" | bc) -eq 1 ] 

Các lỗi mà bạn nhìn thấy mặc dù là do test lệnh (tức là [) cần không gian trước và sau khi

Nó thậm chí còn tốt hơn để sử dụng ((...)) kể từ khi bạn so sánh con số như thế này:

if (($(bc <<< "$test > $k"))) 

phần trong vòng lặp sẽ trông như thế này:

if (($(bc <<< "$test <= 1"))) 
then 
    echo "output" 
elif (($(bc <<< "$test > $k"))) 
then 
    echo "output$k" 
fi 

Biểu thức quan hệ đánh giá là 0, nếu quan hệ là sai và 1 nếu quan hệ là đúng [source]. Tuy nhiên, lưu ý rằng đó là hành vi của GNU bc và không phải là POSIX tương đồng.

+1

Ngoài ra: bash: [: 1.3: biểu thức số nguyên dự kiến ​​sẽ là lỗi nếu bạn đã định dạng biểu thức [] chính xác. + 1 @ user000001 –

+0

Cảm ơn bạn! Nó hoạt động. Câu hỏi nhỏ, tôi đang cố gắng nhìn vào. Tôi muốn người đầu tiên nếu là hoặc ít hơn hoặc bằng 1 và những người khác nghiêm ngặt cao hơn k. Tôi có thể viết (($ (bc <<< "$ test <1" && "$ test = 1") == 1)) hay (($ (bc <<< "$ test <= 1") == 1))? – user1983400

+0

Điều thứ hai là chính xác. Việc đầu tiên sẽ được chính xác nó bạn trích dẫn như thế này: '(($ (bc <<<" $ test <1 && $ test == 1 ") == 1))' (nore cũng là '=='). Để biết thêm thông tin về các biểu thức boolean trong 'bc', hãy xem tại đây: http://www.gnu.org/software/bc/manual/html_mono/bc.html#SEC12 – user000001

9

Loại câu hỏi cũ, nhưng nó có thêm câu trả lời tôi nghĩ.

Trong khi đường ống đến máy tính chính xác cao hơn (bc hoặc dc) hoạt động, chi phí của một ngã ba và một quá trình bổ sung, vì những máy tính này không được xây dựng để bash. Tuy nhiên, một điều mà IS được tích hợp là printf. Vì vậy, nếu bạn có thể đối phó với những con số của bạn là trong một số cụ thể của chữ số thập phân, bạn có thể "giả" nổi so sánh điểm, với một chức năng như thế này:

#!/usr/bin/env bash 

function [[[() { 
    local LANG=C lhs rhs 
    printf -v lhs '%07.3f' "$1"; lhs=${lhs/./} 
    printf -v rhs '%07.3f' "$3"; rhs=${rhs/./} 
    case "$2" in 
    -lt) return $((! (10#$lhs < 10#$rhs))) ;; 
    -le) return $((! (10#$lhs <= 10#$rhs))) ;; 
    -eq) return $((! (10#$lhs == 10#$rhs))) ;; 
    -ge) return $((! (10#$lhs >= 10#$rhs))) ;; 
    -gt) return $((! (10#$lhs > 10#$rhs))) ;; 
    esac 
} 

number=${1:-43} 
test=$(dc -e "2k $number 50/p") 
echo "$test" 

for k in {1..5}; do 
    if [[[ "$test" -le 1 ]]]; then 
     echo "output" 
    elif [[[ "$test" -gt "$k" ]]]; then 
     echo "output $k" 
    fi 
done 

Một vài điều cần xem xét ở đây.

  • Tôi đã đặt tên hàm [[[ trở nên dễ thương. Bạn có thể đặt tên cho nó bất cứ điều gì bạn thích. ntest hoặc mynumericcomparison hoặc thậm chí [[[.
  • printf là một chức năng nội bộ trong bash, vì vậy mặc dù thực tế là nó trên con đường của bạn, nó không chi phí một ngã ba.
  • Vì nó đứng, chức năng hỗ trợ số lên đến 999.999. Nếu bạn cần số cao hơn (hoặc chính xác hơn), hãy điều chỉnh định dạng printf.
  • 10# ở đầu mỗi biến trong câu lệnh case là bắt buộc sự so sánh xảy ra ở cơ sở 10, vì số không đệm có thể được hiểu là bát phân.

Xem thêm: http://mywiki.wooledge.org/BashFAQ/022

+1

Điều đó có vẻ khá tốt nhưng vì lợi ích của copy-pasters tôi muốn đặt định dạng 'printf' thành một cái gì đó hợp lý hơn (phao có thể khá dài, và giữ độ chính xác thấp sẽ không làm cho chức năng này nhanh hơn). –

Các vấn đề liên quan