如何让BASH正确识别两位小数版本号大于一位小数版本号?
解决BASH中两位小数版本号大于一位小数版本的判断问题
我太懂这个版本号比较的坑了!你说的没错,直接用字符串比较或者把版本号当成浮点数丢给bc,都会因为规则不符搞出反结果——毕竟字符串比的是字符顺序,而1.12作为浮点数其实是小于1.8的,但咱们要的是主版本相同的情况下,次版本数字越大版本越高,对吧?下面给你几个靠谱的解决办法:
方法1:用GNU sort的版本排序功能(最省心)
GNU的sort工具自带-V参数,专门用来按版本号规则排序,完美适配这种场景。我们可以利用它来检查两个版本的顺序:
current_version="1.12" target_version="1.8" # 打印两个版本,用sort -V检查是否current_version在target_version之后(即更大) if printf "%s\n%s" "$target_version" "$current_version" | sort -V -c; then echo "$current_version > $target_version" else echo "$current_version <= $target_version" fi
原理很简单:sort -V会按照版本号的逻辑排序,-c参数会验证输入是否已经是有序的。如果我们把目标版本放在前面,当前版本放在后面,排序后顺序不变的话,就说明当前版本更大。这个方法还能兼容更复杂的版本号,比如1.12.3 vs 1.8.1,甚至带字母的1.12a vs 1.8b。
方法2:拆分主/次版本号,分别比较整数
如果你的环境没有GNU sort(比如某些BSD系统),可以手动拆分版本号的主、次部分,分别作为整数比较:
compare_versions() { local ver1=$1 local ver2=$2 # 拆分主版本和次版本 local major1=$(echo "$ver1" | awk -F. '{print $1}') local minor1=$(echo "$ver1" | awk -F. '{print $2}') local major2=$(echo "$ver2" | awk -F. '{print $1}') local minor2=$(echo "$ver2" | awk -F. '{print $2}') # 先比主版本,主版本相同再比次版本 if (( major1 > major2 )); then return 0 # ver1更大 elif (( major1 == major2 )); then if (( minor1 > minor2 )); then return 0 fi fi return 1 # ver1更小或相等 } # 使用示例 version="1.12" if compare_versions "$version" "1.8"; then echo "$version 大于 1.8" else echo "$version 小于等于 1.8" fi
这个方法逻辑清晰,完全用BASH的整数比较,不会有字符串或浮点数的坑,适合需要精确控制比较逻辑的场景。
方法3:给次版本补零后转整数(简单粗暴)
另一种思路是把版本号转换成统一长度的整数,比如把次版本补零到3位(足够覆盖大部分场景),然后合并成一个大整数比较:
version="1.12" target="1.8" # 拆分并补零 ver_int=$(echo "$version" | awk -F. '{printf "%d%03d", $1, $2}') tar_int=$(echo "$target" | awk -F. '{printf "%d%03d", $1, $2}') if (( ver_int > tar_int )); then echo "$version > $target" else echo "$version <= $target" fi
这里1.12会变成1012,1.8变成1008,整数比较就完全符合我们的预期了。
之前你用bc没成功,大概率是因为把版本号当成了浮点数——毕竟1.12作为浮点数确实小于1.8,但咱们的版本号是主/次版本的组合,不是单一的小数,所以不能这么比啦!
内容的提问来源于stack exchange,提问作者hobbes
相关产品推荐
相关产品推荐

