
1. 为什么if [ 120.254 -gt 111.91 ]会直接报错先说结论Shell 的[ ]也就是test命令只认整数不认小数。你写if [ 120.254 -gt 111.91 ]它不会帮你做数值比较而是直接甩一句integer expression expected然后走 else 分支。更坑的是如果你用、这种写法它根本不报错但结果完全是错的——因为在[ ]里被当成字符串比较120.254 111.91按字典序比第一位1和1相等第二位2和1比2 1所以返回假逻辑直接翻车。这个场景在运维脚本里特别常见磁盘使用率、接口响应耗时、温度传感器读数、价格阈值判断只要带小数点用-gt、-lt、-eq就会踩坑。expr也一样它只处理整数expr 111.91 \ 95会返回 0判断结果和真实大小关系相反。那怎么办最稳的办法是把比较表达式交给bc去算bc支持任意精度小数算完返回1真或0假Shell 再拿这个结果做if判断。下面我把整套可复制的写法、边界用例和排错过程拆开讲你照着改脚本就行。2. 前置准备确认 bc 可用并理解它的返回约定bc是 POSIX 标准里就有的任意精度计算器绝大多数 Linux 发行版默认带macOS 也有。先确认一下which bc bc --version如果提示找不到Debian/Ubuntu 系用apt-get install bcRHEL/CentOS 系用yum install bcAlpine 用apk add bc。装完再跑一次which bc确认路径。这里有个关键点必须先记住bc的比较表达式返回1表示真返回0表示假。比如echo 120.254 111.91 | bc # 输出 1 echo 120.254 111.91 | bc # 输出 0所以 Shell 里的判断写法就是if [ $(echo A B | bc) 1 ]。注意bc默认不输出前导空格但为了保险比较时最好用 1而不是 1因为[ ]里不是 POSIX 标准写法bash能认sh/dash可能报错。另外提醒一句bc默认的scale是 0但比较运算不受scale影响它比较的是真实数值大小不会因为精度截断而误判。这点比很多手写解析脚本靠谱。3. 可复制配置if 里用 bc 比较小数的三种写法3.1 最基础写法单行内联#!/bin/bash a120.254 b111.91 if [ $(echo $a $b | bc) -eq 1 ]; then echo $a is bigger else echo $b is bigger fi运行结果120.254 is bigger这里用-eq 1和 1都行-eq是整数比较bc返回的就是整数 0/1所以没问题。我一般用-eq 1语义更清楚。3.2 封装成函数脚本里反复调用如果脚本里要判断很多次每次都写$(echo ... | bc)太啰嗦封装一个函数更清爽#!/bin/bash # 用法: float_gt A B - A B 返回 0(真), 否则返回 1(假) float_gt() { [ $(echo $1 $2 | bc) -eq 1 ] } float_lt() { [ $(echo $1 $2 | bc) -eq 1 ] } float_ge() { [ $(echo $1 $2 | bc) -eq 1 ] } float_eq() { [ $(echo $1 $2 | bc) -eq 1 ] } a120.254 b111.91 if float_gt $a $b; then echo a b fi if float_lt $b $a; then echo b a fi注意函数里用的是[ ... ]的退出码if直接吃退出码所以调用时不用再套$(...)。这种写法在监控脚本里特别顺手比如判断磁盘使用率是否超过 85.5%usage87.32 if float_gt $usage 85.5; then echo 磁盘使用率告警: ${usage}% fi3.3 用 here-string 避免管道子 shell 开销echo ... | bc每次都会起一个子 shell 和管道循环里跑几千次会有性能损耗。可以用 here-stringbash 专属或者bc if [ $(bc $a $b) -eq 1 ]; then echo bigger fi是 bash 的 here-string少一层管道速度快一点。但注意sh/dash不支持如果脚本要兼容 POSIX还是用echo | bc最稳。3.4 参数对照表比较需求bc 表达式Shell 判断写法A 大于 BA B[ $(echo A B | bc) -eq 1 ]A 小于 BA B[ $(echo A B | bc) -eq 1 ]A 大于等于 BA B[ $(echo A B | bc) -eq 1 ]A 小于等于 BA B[ $(echo A B | bc) -eq 1 ]A 等于 BA B[ $(echo A B | bc) -eq 1 ]A 不等于 BA ! B[ $(echo A ! B | bc) -eq 1 ]注意bc里判断相等用不是。写会变成赋值结果不可预期。4. 验证请求与成功结果边界用例逐个跑光看写法不够得拿边界值验证。下面这段脚本把正数、负数、零、相等、极小数、大数都覆盖一遍你可以直接存成test_float.sh跑#!/bin/bash float_gt() { [ $(echo $1 $2 | bc) -eq 1 ]; } float_eq() { [ $(echo $1 $2 | bc) -eq 1 ]; } check() { local a$1 b$2 expect$3 if float_gt $a $b; then resultgt elif float_eq $a $b; then resulteq else resultlt fi if [ $result $expect ]; then echo PASS: $a vs $b - $result else echo FAIL: $a vs $b - $result (expect $expect) fi } check 120.254 111.91 gt check 111.91 120.254 lt check 0.001 0.0009 gt check -5.5 -5.4 lt check 0.0 0.00 eq check 100.000 100 eq check 3.1415926 3.1415927 lt check 999999.99 1000000.01 lt预期输出全是PASS。我实测下来bc对0.0和0.00判等返回 1对-5.5和-5.4的大小关系也正确负数不会翻车。这一点比某些手写字符串解析靠谱得多。如果你在脚本里读的是外部输入比如从df或awk拿到的使用率记得先去掉百分号usage$(df -h / | awk NR2 {print $5} | tr -d %) if float_gt $usage 85.5; then echo 告警 fitr -d %把87%变成87再进bc比较。如果输入里混了非数字字符bc会报语法错误所以生产脚本里最好加一层校验if ! [[ $usage ~ ^-?[0-9](\.[0-9])?$ ]]; then echo 非法数值: $usage 2 exit 1 fi5. 本篇常见错排查报错一integer expression expected原因就是用了[ 120.254 -gt 111.91 ]。-gt只接受整数遇到小数点直接报错。改成bc写法即可。报错二(standard_in) 1: syntax errorbc收到的表达式里有非法字符常见于变量里带了%、空格、单位。先tr -d %或sed清洗再用正则校验。报错三判断结果和预期相反大概率是用了[ 120.254 111.91 ]这种字符串比较。在[ ]里不是数值比较是字典序比较结果不可信。统一换成bc。报错四bc命令找不到容器镜像里没装bc。Alpine 用apk add bcDebian 用apt-get install -y bc。如果实在不能装可以用awk替代if awk BEGIN{exit !($a $b)}; then echo bigger fiawk的exit !(条件)技巧也能做小数比较但可读性不如bc而且awk的浮点精度受实现影响bc更可控。报错五变量为空导致bc报错a或b没赋值时echo 111.91 | bc会语法错误。加默认值或前置校验a${a:-0} b${b:-0}报错六sh下不认脚本 shebang 是#!/bin/sh时bc ...会报Syntax error: redirection unexpected。要么改成#!/bin/bash要么退回echo | bc。6. 把判断逻辑接进你的脚本工作流小数比较本身不复杂难的是在真实脚本里稳定跑。我的建议是把float_gt、float_lt这几个函数抽到一个公共lib.sh里所有监控、告警、阈值判断脚本都source它避免每个脚本重复写bc管道。输入侧统一做正则校验输出侧统一用退出码这样if判断就干净了。如果你在写的是长期跑的 Agent 或自动化任务需要频繁调用模型做决策、再回到 Shell 里做数值判断可以把这类脚本逻辑和模型调用分开管理。模型对话和 API Key 的入口在 TaoToken 模型对话 和 API Keys 管理接入细节看 接入文档。要是你打算把这类判断脚本挂到 Coding Plan 的自动化流程里长期跑Coding Plan 那边有更完整的任务编排说明。最后留一个我常用的调试技巧在bc比较前先把表达式打印出来echo compare: $a $b确认变量值符合预期再进if。很多“判断反了”的问题其实是变量里混了空格或换行bc把120.254当成合法数字但111.91前面的空格在某些版本里会触发解析差异。打印一次省半小时排查。