shell 比较浮点数大小的问题,顺便吐槽以下 shell - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
OldCarMan
V2EX    Bash

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

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

    平时比较少写 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     Solana     2510 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 04:32 PVG 12:32 LAX 20:32 JFK 23:32
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86