【问题标题】:How to compare two decimal numbers in bash/awk?如何比较bash / awk中的两个十进制数字?
【发布时间】:2012-06-29 13:39:17
【问题描述】:

我正在尝试比较两个十进制值,但出现错误。 我用过

if [ "$(echo $result1 '>' $result2 | bc -l)" -eq 1 ];then

正如其他 Stack Overflow 线程所建议的那样。

我遇到了错误。

解决这个问题的正确方法是什么?

【问题讨论】:

  • 有什么错误?一个变量名拼错了。
  • 实际上这些错误是由于其他一些问题造成的。这工作正常。
  • “十进制值”是什么意思?您是指以 10 为底的整数,还是表示非整数实数值的字符串?
  • @WilliamPursell:我假设由于 OP 使用的是bc,尤其是与-l 一起使用,因此正在比较浮点数。不过,比较不需要-l

标签: bash shell awk


【解决方案1】:

对于 shell 脚本,我不能使用双括号 (())。所以,帮助我的是将它分成两行并以经典方式进行比较。

low_limit=4.2
value=3.9
        
result=$(echo "${value}<${low_limit}" | bc)
    
if [ $result = 1 ]; then
  echo too low; 
else 
  echo not too low; 
fi

【讨论】:

    【解决方案2】:
    if [[ `echo "$result1 $result2" | awk '{print ($1 > $2)}'` == 1 ]]; then
      echo "$result1 is greater than $result2"
    fi
    

    【讨论】:

      【解决方案3】:

      跟进丹尼斯的回复:

      虽然他的回答对于小数点是正确的,但 bash 会抛出 (standard_in) 1: syntax error 与浮点运算。

      result1=12
      result2=1.27554e-05
      
      
      if (( $(echo "$result1 > $result2" | bc -l) )); then
          echo "r1 > r2"
      else
          echo "r1 < r2"
      fi
      

      尽管退出代码为 0,但会返回错误输出并发出警告。

      (standard_in) 1:语法错误
      r1

      虽然对此没有明确的解决方案(讨论thread 1thread 2),但我使用了以下部分修复方法,使用awk 舍入浮点结果,然后使用bc 命令,如丹尼斯的回复和this thread

      四舍五入到所需的小数位:以下将得到以 TB 为单位的递归目录空间,四舍五入到小数点后第二位。

      result2=$(du -s "/home/foo/videos" | tail -n1 | awk '{$1=$1/(1024^3); printf "%.2f", $1;}')
      

      然后您可以像上面那样使用 bash 算术,或者像在 following thread 中那样使用 [[ ]] 附件。

      if (( $(echo "$result1 > $result2" | bc -l) )); then
          echo "r1 > r2"
      else
          echo "r1 < r2"
      fi
      

      或使用-eq 运算符,其中bc 输出1 为true,0 为false

      if [[ $(bc <<< "$result1 < $result2") -eq 1 ]]; then
          echo "r1 < r2"
      else
          echo "r1 > r2"
      fi
      

      【讨论】:

        【解决方案4】:
        if awk 'BEGIN{exit ARGV[1]>ARGV[2]}' "$z" "$y"
        then
          echo z not greater than y
        else
          echo z greater than y
        fi
        

        【讨论】:

        • 对于那些和我一样困惑的人来说,在 AWK 语言中,布尔语句的值为 1 如果为真,如果不是,则为 0,与 UNIX shell 相反。因此,在使用上述 AWK 程序的 shell 脚本中,必须还原结果,例如使用 {exit !(ARGV[1]>ARGV[2])} 来获取对应于比较 ARGV[1]>ARGV[ 的 shell 退出代码2].
        【解决方案5】:

        不能 bash 强制类型转换?例如:

        ($result1 + 0) < ($result2 + 0)
        

        【讨论】:

        • () 构造将封闭的文本作为命令运行,它不做任何算术运算。看起来您将它与 ((...)) 运算符混淆了。
        【解决方案6】:

        为什么要使用 bc ?

        for i in $(seq -3 0.5 4) ; do echo $i ; if [[ (( "$i" < 2 )) ]] ; then echo "... is < 2";fi; done
        

        唯一的问题:比较“

        【讨论】:

        • &lt; inside [[...]] 用于字符串比较(所以20 小于30.2 小于1e-50)。 ( 是多余的,您可以添加任意数量,它们仅用于分组。
        【解决方案7】:

        您也可以将echoif...else 声明为bc

        - echo $result1 '>' $result2
        + echo "if (${result1} > ${result2}) 1 else 0"
        
        (
        #export IFS=2  # example why quoting is important
        result1="2.3" 
        result2="1.7" 
        if [ "$(echo $result1 '>' $result2 | bc -l)" -eq 1 ]; then echo yes; else echo no;fi
        if [ "$(echo "if (${result1} > ${result2}) 1 else 0" | bc -l)" -eq 1 ];then echo yes; else echo no; fi
        if echo $result1 $result2 | awk '{exit !( $1 > $2)}'; then echo yes; else echo no; fi
        )
        

        【讨论】:

          【解决方案8】:

          您可以使用 Bash 的数字上下文来做到这一点:

          if (( $(echo "$result1 > $result2" | bc -l) )); then
          

          bc 将输出 0 或 1,(( )) 将分别将它们解释为 false 或 true。

          使用 AWK 做同样的事情:

          if (( $(echo "$result1 $result2" | awk '{print ($1 > $2)}') )); then
          

          【讨论】:

          • +1 表示 awk 解决方案,但是:if echo $result1 $result2 | awk '{exit !( $1 &gt; $2)}'; then ...
          • 我想撤回我的反对票,因为丹尼斯的回复是正确的,带有小数点。有关使用 bash 的扩展浮点运算,请参阅下面的回复。
          • @Samir:如果你还没有,你可以再次点击向下箭头来取消投票。
          • @DennisWilliamson 它说我的投票已被锁定,除非有人编辑此答案,否则无法编辑。
          • +1 @WilliamPursell 但使用 awk "BEGIN {exit !(${result1} &gt; ${result2})}" 而不是通过管道将 echo 输入 awk。
          猜你喜欢
          • 1970-01-01
          • 2012-08-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-14
          • 1970-01-01
          • 2013-10-26
          相关资源
          最近更新 更多