是否有办法在bash上比较这些字符串,例如:2.4.5和2.8和2.4.5.1?
当前回答
我希望这对某些人有用(使用awk)
#!/bin/bash
available_version=1.2.3 # or online version
this_version=1.2.1
if [[ "ok" == "$(echo | awk "(${available_version} > ${this_version}) { print \"ok\"; }")" ]]; then
echo "Notice, new version is available"
elif [[ "ok" == "$(echo | awk "(${available_version} == ${this_version}) { print \"ok\"; }")" ]]; then
echo "OK, version is up to date"
else
echo "Warning, the current version is ahead of the online version!"
fi
其他回答
哇……这是一个老问题,但我认为这是一个相当优雅的答案。首先,使用shell参数展开(参见shell参数展开)将每个点分隔的版本转换为自己的数组。
v1="05.2.3" # some evil examples that work here
v2="7.001.0.0"
declare -a v1_array=(${v1//./ })
declare -a v2_array=(${v2//./ })
现在,这两个数组将版本号按优先级顺序作为数值字符串。上面的许多解决方案都是从这里开始的,但它们都源于这样的观察:版本字符串只是一个具有任意基数的整数。我们可以测试找到第一个不相等的数字(就像strcmp对字符串中的字符所做的那样)。
compare_version() {
declare -a v1_array=(${1//./ })
declare -a v2_array=(${2//./ })
while [[ -nz $v1_array ]] || [[ -nz $v2_array ]]; do
let v1_val=${v1_array:-0} # this will remove any leading zeros
let v2_val=${v2_array:-0}
let result=$((v1_val-v2_val))
if (( result != 0 )); then
echo $result
return
fi
v1_array=("${v1_array[@]:1}") # trim off the first "digit". it doesn't help
v2_array=("${v2_array[@]:1}")
done
# if we get here, both the arrays are empty and neither has been numerically
# different, which is equivalent to the two versions being equal
echo 0
return
}
如果第一个版本小于第二个版本,则返回负数,如果相等则返回零,如果第一个版本大于第二个版本则返回正数。一些输出:
$ compare_version 1 1.2
-2
$ compare_version "05.1.3" "5.001.03.0.0.0.1"
-1
$ compare_version "05.1.3" "5.001.03.0.0.0"
0
$ compare_version "05.1.3" "5.001.03.0"
0
$ compare_version "05.1.3" "5.001.30.0"
-27
$ compare_version "05.2.3" "7.001.0.0"
-2
$ compare_version "05.1.3" "5.001.30.0"
-27
$ compare_version "7.001.0.0" "05.1.3"
2
堕落的例子,”。2”或“3.0.”不起作用(未定义的结果),并且如果'. 2 '旁边出现非数字字符。它可能会失败(还没有测试),但肯定是没有定义的。因此,这应该与一个消毒函数或适当的检查有效的格式相匹配。此外,我相信通过一些调整,可以在没有太多额外负担的情况下使其更加健壮。
你们都给出了复杂的解决方案。这里有一个更简单的例子。
function compare_versions {
local a=${1%%.*} b=${2%%.*}
[[ "10#${a:-0}" -gt "10#${b:-0}" ]] && return 1
[[ "10#${a:-0}" -lt "10#${b:-0}" ]] && return 2
a=${1:${#a} + 1} b=${2:${#b} + 1}
[[ -z $a && -z $b ]] || compare_versions "$a" "$b"
}
用法:compare_versions <ver_a> <ver_b>
返回代码1表示第一个版本大于第二个版本,2表示小于第二个版本,0表示两者相等。
也是一个非递归的版本:
function compare_versions {
local a=$1 b=$2 x y
while [[ $a || $b ]]; do
x=${a%%.*} y=${b%%.*}
[[ "10#${x:-0}" -gt "10#${y:-0}" ]] && return 1
[[ "10#${x:-0}" -lt "10#${y:-0}" ]] && return 2
a=${a:${#x} + 1} b=${b:${#y} + 1}
done
return 0
}
与其编写冗长的代码使您的生活过于复杂,不如使用一些已经存在的东西。很多时候,当bash不够用时,python可以提供帮助。你仍然可以很容易地从bash脚本调用它(额外的好处:从bash到python的变量替换):
VERSION1=1.2.3
VERSION2=1.2.4
cat <<EOF | python3 | grep -q True
from packaging import version
print(version.parse("$VERSION1") > version.parse("$VERSION2"))
EOF
if [ "$?" == 0 ]; then
echo "$VERSION1 is greater than $VERSION2"
else
echo "$VERSION2 is greater or equal than $VERSION1"
fi
这里有更多信息:如何比较Python中的版本号?
您可以通过版本命令行查看版本约束
$ version ">=1.0, <2.0" "1.7"
$ go version | version ">=1.9"
Bash脚本示例:
#!/bin/bash
if `version -b ">=9.0.0" "$(gcc --version)"`; then
echo "gcc version satisfies constraints >=9.0.0"
else
echo "gcc version doesn't satisfies constraints >=9.0.0"
fi
我遇到并解决了这个问题,添加了一个额外的(更短更简单的)答案…
首先注意,扩展shell比较失败了,你可能已经知道了…
if [[ 1.2.0 < 1.12.12 ]]; then echo true; else echo false; fi
false
使用sort -t'。'-g(或者kanaka提到的sort -V)来排序版本和简单的bash字符串比较,我找到了一个解决方案。输入文件包含列3和列4中的版本,我想对它们进行比较。这将遍历列表,确定匹配项或其中一个大于另一个。希望这仍然可以帮助那些希望使用bash尽可能简单地做到这一点的人。
while read l
do
#Field 3 contains version on left to compare (change -f3 to required column).
kf=$(echo $l | cut -d ' ' -f3)
#Field 4 contains version on right to compare (change -f4 to required column).
mp=$(echo $l | cut -d ' ' -f4)
echo 'kf = '$kf
echo 'mp = '$mp
#To compare versions m.m.m the two can be listed and sorted with a . separator and the greater version found.
gv=$(echo -e $kf'\n'$mp | sort -t'.' -g | tail -n 1)
if [ $kf = $mp ]; then
echo 'Match Found: '$l
elif [ $kf = $gv ]; then
echo 'Karaf feature file version is greater '$l
elif [ $mp = $gv ]; then
echo 'Maven pom file version is greater '$l
else
echo 'Comparison error '$l
fi
done < features_and_pom_versions.tmp.txt
感谢Barry的博客给出了排序的想法…… 裁判:http://bkhome.org/blog/?viewDetailed=02199