有没有办法比较的庆典,如这样的字符串:2.4.5
和2.8
和2.4.5.1
?
这是一个纯Bash版本,不需要任何外部实用程序:
#!/bin/bash vercomp () { if [[ $1 == $2 ]] then return 0 fi local IFS=. local i ver1=($1) ver2=($2) # fill empty fields in ver1 with zeros for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) do ver1[i]=0 done for ((i=0; i<${#ver1[@]}; i++)) do if [[ -z ${ver2[i]} ]] then # fill empty fields in ver2 with zeros ver2[i]=0 fi if ((10#${ver1[i]} > 10#${ver2[i]})) then return 1 fi if ((10#${ver1[i]} < 10#${ver2[i]})) then return 2 fi done return 0 } testvercomp () { vercomp $1 $2 case $? in 0) op='=';; 1) op='>';; 2) op='<';; esac if [[ $op != $3 ]] then echo "FAIL: Expected '$3', Actual '$op', Arg1 '$1', Arg2 '$2'" else echo "Pass: '$1 $op $2'" fi } # Run tests # argument table format: # testarg1 testarg2 expected_relationship echo "The following tests should pass" while read -r test do testvercomp $test done << EOF 1 1 = 2.1 2.2 < 3.0.4.10 3.0.4.2 > 4.08 4.08.01 < 3.2.1.9.8144 3.2 > 3.2 3.2.1.9.8144 < 1.2 2.1 < 2.1 1.2 > 5.6.7 5.6.7 = 1.01.1 1.1.1 = 1.1.1 1.01.1 = 1 1.0 = 1.0 1 = 1.0.2.0 1.0.2 = 1..0 1.0 = 1.0 1..0 = EOF echo "The following test should fail (test the tester)" testvercomp 1 1 '>'
运行测试:
$ . ./vercomp The following tests should pass Pass: '1 = 1' Pass: '2.1 < 2.2' Pass: '3.0.4.10 > 3.0.4.2' Pass: '4.08 < 4.08.01' Pass: '3.2.1.9.8144 > 3.2' Pass: '3.2 < 3.2.1.9.8144' Pass: '1.2 < 2.1' Pass: '2.1 > 1.2' Pass: '5.6.7 = 5.6.7' Pass: '1.01.1 = 1.1.1' Pass: '1.1.1 = 1.01.1' Pass: '1 = 1.0' Pass: '1.0 = 1' Pass: '1.0.2.0 = 1.0.2' Pass: '1..0 = 1.0' Pass: '1.0 = 1..0' The following test should fail (test the tester) FAIL: Expected '>', Actual '=', Arg1 '1', Arg2 '1'
如果你有coreutils-7(在Ubuntu Karmic而不是Jaunty),那么你的sort
命令应该有一个-V
选项(版本排序),你可以使用它来进行比较:
verlte() { [ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ] } verlt() { [ "$1" = "$2" ] && return 1 || verlte $1 $2 } verlte 2.5.7 2.5.6 && echo "yes" || echo "no" # no verlt 2.4.10 2.4.9 && echo "yes" || echo "no" # no verlt 2.4.8 2.4.10 && echo "yes" || echo "no" # yes verlte 2.5.6 2.5.6 && echo "yes" || echo "no" # yes verlt 2.5.6 2.5.6 && echo "yes" || echo "no" # no
可能没有普遍正确的方法来实现这一目标.如果您正在尝试比较Debian软件包系统中的版本,请尝试dpkg --compare-versions
GNU sort有一个选项:
printf '2.4.5\n2.8\n2.4.5.1\n' | sort -V
得到:
2.4.5 2.4.5.1 2.8
好吧,如果你知道你可以使用的字段数-kn,n并获得一个超级简单的解决方案
echo '2.4.5 2.8 2.4.5.1 2.10.2' | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -k 4,4 -g 2.4.5 2.4.5.1 2.8 2.10.2
这适用于版本中最多4个字段.
$ function ver { printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' ' '); } $ [ $(ver 10.9) -lt $(ver 10.10) ] && echo hello hello
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
用作这样的:
if [ $(version $VAR) -ge $(version "6.2.0") ]; then echo "Version is up to date" fi
(来自https://apple.stackexchange.com/a/123408/11374)
您可以递归拆分.
并进行比较,如下面的算法所示,取自此处.如果版本相同则返回10,如果版本1大于版本2则返回11,否则返回9.
#!/bin/bash do_version_check() { [ "$1" == "$2" ] && return 10 ver1front=`echo $1 | cut -d "." -f -1` ver1back=`echo $1 | cut -d "." -f 2-` ver2front=`echo $2 | cut -d "." -f -1` ver2back=`echo $2 | cut -d "." -f 2-` if [ "$ver1front" != "$1" ] || [ "$ver2front" != "$2" ]; then [ "$ver1front" -gt "$ver2front" ] && return 11 [ "$ver1front" -lt "$ver2front" ] && return 9 [ "$ver1front" == "$1" ] || [ -z "$ver1back" ] && ver1back=0 [ "$ver2front" == "$2" ] || [ -z "$ver2back" ] && ver2back=0 do_version_check "$ver1back" "$ver2back" return $? else [ "$1" -gt "$2" ] && return 11 || return 9 fi } do_version_check "$1" "$2"
资源
如果只是想知道一个版本是否低于另一个版本,我会检查是否sort --version-sort
更改了版本字符串的顺序:
string="$1 $2" [ "$string" == "$(sort --version-sort <<< "$string")" ]
我实现了一个函数,该函数返回与Dennis Williamson相同的结果,但使用的行数更少。它最初会执行健全性检查,这会导致1..0
他的测试失败(我认为应该是这种情况),但他的所有其他测试均通过以下代码通过:
#!/bin/bash version_compare() { if [[ $1 =~ ^([0-9]+\.?)+$ && $2 =~ ^([0-9]+\.?)+$ ]]; then local l=(${1//./ }) r=(${2//./ }) s=${#l[@]}; [[ ${#r[@]} -gt ${#l[@]} ]] && s=${#r[@]} for i in $(seq 0 $((s - 1))); do [[ ${l[$i]} -gt ${r[$i]} ]] && return 1 [[ ${l[$i]} -lt ${r[$i]} ]] && return 2 done return 0 else echo "Invalid version number given" exit 1 fi }