V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
OldCarMan
V2EX  ›  Bash

shell 比较浮点数大小的问题,顺便吐槽以下 shell

  •  
  •   OldCarMan · 2023-03-13 09:19:17 +08:00 · 2169 次点击
    这是一个创建于 650 天前的主题,其中的信息可能已经有所发展或是发生改变。

    平时比较少写 shell ,最近因为需要,写 shell 时,发现 shell 的语法真的让人头大,比如简单的比较两个浮点数大小:

    a=0.1
    b=0.01
    if (( $(echo "$a > $b" |bc -l) )); then
      ehco "true"
    else
      echo "false"
    fi
    
    a=0.1
    b=0.01
    if [ $(echo "$a > $b"|bc) -eq 1 ];then
        echo "true"
    else
        echo "false"
    fi
    
    都有问题(都输出 false),常用的>,<,gt,lt 又没办法直接比较浮点数大小,简直了😂。

    PS:另外用 vim 写 shell 时经常性遇到空格之类的问题,大佬们平时是不是用 shell 比较少,是用 python 或 lua 较多吗?

    第 1 条附言  ·  2023-03-14 08:43:53 +08:00
    总结一下,平时写shell时(linux运行环境),浮点数比较的几种方式:
    • 使用 #1 楼说的 awk方式,自带。
    • 使用 #15 楼说的 用python,不过我看我的centos(8.5)默认没自带,需要额外安装。
    • 使用 #16 楼说的 perl方式,自带。
    • bc库,也就是我描述里说的那种,我系统也没有自带,需要额外安装bc库。
    19 条回复    2023-03-25 00:06:31 +08:00
    startisan
        1
    startisan  
       2023-03-13 09:43:01 +08:00
    OP 方式 1 输出 true 的 echo 拼写错了。

    我来补充个方式 3 ,个人更喜欢用这个,有时候数据本来就要用 awk 获取,正好 awk 就能比较:
    echo "$a" "$b" | awk '{if ($1 < $2) pring "false"; else print "true"}'
    Donahue
        2
    Donahue  
       2023-03-13 09:43:51 +08:00
    用了 linux 4 年多了,还不会 shell, 需要的时候才查...
    实在记不住这些,不常用,语法规则又那么奇怪
    OldCarMan
        3
    OldCarMan  
    OP
       2023-03-13 09:52:56 +08:00
    @startisan 是的,刚刚手打错字了,好的,谢谢大佬。
    @是啊,语法太难用了。
    刚刚在服务器重新跑了下,发现是我用 tee 命令时,有些代码片段“被吃掉了”的缘故:

    不好意思,个人粗心,让大家费心了。
    OldCarMan
        4
    OldCarMan  
    OP
       2023-03-13 09:56:06 +08:00
    不过,shell 实在一言难尽,最基本的浮点比较,也必须安装一个 bc 库才能用。
    Rache1
        5
    Rache1  
       2023-03-13 09:56:17 +08:00
    😂 我都是用 php 写,有时候需要调用 shell ,就用内置的函数执行 shell 命令。
    lakehylia
        6
    lakehylia  
       2023-03-13 09:57:38 +08:00
    @startisan 哈哈,大哥你的 print 也拼写错了
    OldCarMan
        7
    OldCarMan  
    OP
       2023-03-13 10:03:00 +08:00
    我上面#4 说错了,@startisan 这种更好使,而且不需要安装 bc 库
    OldCarMan
        8
    OldCarMan  
    OP
       2023-03-13 10:07:11 +08:00
    @Rache1 嗯嗯,脚本写的很少,之前就用 python 写过一点数据同步的,你后端如果也是 php 开发的,用 php 就够了。不过我还是不大想安装太多额外的库+业务不复杂,所以直接使用 shell 。
    churchmice
        9
    churchmice  
       2023-03-13 10:07:37 +08:00
    你具体展开说说 shell 碰到空格问题是啥问题
    你只要理解了 [ 其实也是一个命令,就不会有这么多疑惑了
    which [
    看一下就知道了
    做事要理解原理
    startisan
        10
    startisan  
       2023-03-13 10:23:36 +08:00
    @lakehylia #6 哈哈,我要被自己笑死了,我发之前还去环境上跑了下命令。
    yingqiuQAQ
        11
    yingqiuQAQ  
       2023-03-13 10:31:03 +08:00
    属于同是天涯沦落人了。。。 上次写了个内存查询 top -n 1 | grep xxx | awk '{mem_percent += $10} END {print mem_percent}' ,结果值是小数。 用 -gt 判断报错了,裂开来。
    sadfQED2
        12
    sadfQED2  
       2023-03-13 11:13:27 +08:00 via Android
    @Donahue +1 ,shell 语法永远记不住,我一般都是通过 shell 套一个 python
    crysislinux
        13
    crysislinux  
       2023-03-13 11:35:12 +08:00 via Android
    这辈子是搞不清 shell 了。之前写了个要长期运行的 bash script ,老是有内存泄露,百思不得其解,最后换了 nodejs 用同样的逻辑写就好了。。
    idontnowhat2say
        14
    idontnowhat2say  
       2023-03-13 12:20:14 +08:00
    最佳实践是把 shell 当胶水语言用,用来粘合命令,你这种情况应该用 Python 的。
    idontnowhat2say
        15
    idontnowhat2say  
       2023-03-13 12:29:36 +08:00
    ```
    #!/bin/bash
    a=0.1
    b=0.01
    python -c "print($a > $b)"
    ```

    Python 在 Linux 发行版上都自带的,你这需求就三行搞定。
    fzinfz
        16
    fzinfz  
       2023-03-13 19:47:38 +08:00
    来 2 个 perl 版:
    perl -e "print $a > $b ? qq(True\n) : qq(False\n);"
    perl -e "exit($a > $b ? 0 : 1);" && echo "True" || echo "False"
    OldCarMan
        17
    OldCarMan  
    OP
       2023-03-14 08:34:11 +08:00
    @churchmice 谢谢大佬指教,确实如你所说,shell 这方面我确实没去深入了解它的语法,主要平时很少用它,用到时才去写,空格主要是在 vim 上写时,不小心敲多了一个或少一个空格都会报错(习惯了其他语言对这方面没有那么高的要求,另外还有 idea 工作环境),你说得对,凡事从原理出发去学习。
    @yingqiuQAQ 是啊,自带基本只能做整数判断,v 友说的,或者我上面说的都要依赖其他库,不过大部分 linux 都带有了。除了那个 bc 库
    @crysislinux 主要是有时不好调试,复杂业务真不适合用它来做,如 v 友所说用来做胶水层比较好
    @idontnowhat2say 确实。
    @fzinfz 谢谢指教,新方式 get ✔
    aloxaf
        18
    aloxaf  
       2023-03-24 23:12:24 +08:00
    说真的,如果不需要考虑可移植性,写 zsh 脚本更好,很多地方比 bash 顺手多了……

    > (( 0.1 > 0.01)) && echo true || echo false
    false
    > echo $(( 0.1 + 0.01 ))
    0.11
    OldCarMan
        19
    OldCarMan  
    OP
       2023-03-25 00:06:31 +08:00
    @aloxaf 是的,只可惜,兼容性往往是一个重要的需求,当然对于那种有一定规模的脚本来说,如果引用到第三方库之类的,一般也会在脚本里声明和检测的,所以个人觉得看需求和业务量。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2465 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:31 · PVG 13:31 · LAX 21:31 · JFK 00:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.