23

我想将浮点变量与整数进行比较。我知道这不是最好的 bash,但我的整个脚本已经用 bash 编写了。$number 可以是任何整数。如果它低于或等于 50,我想要 output1,对于所有其他人,我想要一个带有另一个变量 k 的输出。这是我到目前为止所拥有的:

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

如果我尝试使用 test=0.43,则第一个循环甚至不起作用。我认为它与整数和浮点比较有关,但不能使其工作。

有什么我想念的吗?

PS:这[0.43: command not found是终端输出的。

4

2 回答 2

45

Bash 无法处理浮点数。管道bc改为:

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

您看到的错误是因为test命令(即[)前后需要空格

使用起来会更好,(( ... ))因为您可以像这样比较数字:

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

循环中的部分应如下所示:

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

如果关系为假,则关系表达式计算为 0,如果关系为真,则计算为 1 [来源]。但是请注意,这是 的行为GNU bc,并且不POSIX符合要求。

于 2013-03-05T13:17:49.003 回答
10

有点老问题,但我认为它还有一个额外的答案。

虽然通过管道连接到更高精度的计算器(bc 或 dc)是可行的,但它是以分叉和额外过程为代价的,因为这些计算器不是内置于 bash 中的。但是,内置的一件事是printf. 因此,如果您可以处理您的数字在特定的小数位数内,您可以使用如下函数“伪造”浮点比较:

#!/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

这里有几件事要考虑。

  • 我把这个函数命名为[[[可爱。你可以随意命名它。ntest或者mynumericcomparison甚至[[[
  • printf是 bash 中的一个内部函数,因此尽管它在您的路径上,但它不需要分叉。
  • 就目前而言,该功能支持最多 999.999 的数字。如果您需要更高的数字(或更精确),请调整printf格式。
  • 语句中每个变量的10#开头case是强制比较在基数 10 处进行,因为零填充的数字可能会被解释为八进制。

另见: http: //mywiki.wooledge.org/BashFAQ/022

于 2015-11-17T14:42:48.053 回答