是否有办法在bash上比较这些字符串,例如:2.4.5和2.8和2.4.5.1?


当前回答

感谢Dennis的解决方案,我们可以扩展它以允许比较运算符'>','<','=','==','<='和'>='。

# compver ver1 '=|==|>|<|>=|<=' ver2
compver() { 
    local op
    vercomp $1 $3
    case $? in
        0) op='=';;
        1) op='>';;
        2) op='<';;
    esac
    [[ $2 == *$op* ]] && return 0 || return 1
}

然后我们可以在表达式中使用比较运算符,比如:

compver 1.7 '<=' 1.8
compver 1.7 '==' 1.7
compver 1.7 '=' 1.7

并且只测试结果的真/假,比如:

if compver $ver1 '>' $ver2; then
    echo "Newer"
fi

其他回答

下面是另一个纯bash版本,比公认的答案要小得多。它只检查版本是否小于或等于“最小版本”,并且它将按字典顺序检查字母数字序列,这通常会给出错误的结果(举个常见的例子,“snapshot”不晚于“release”)。它将工作的主要/次要。

is_number() {
    case "$BASH_VERSION" in
        3.1.*)
            PATTERN='\^\[0-9\]+\$'
            ;;
        *)
            PATTERN='^[0-9]+$'
            ;;
    esac

    [[ "$1" =~ $PATTERN ]]
}

min_version() {
    if [[ $# != 2 ]]
    then
        echo "Usage: min_version current minimum"
        return
    fi

    A="${1%%.*}"
    B="${2%%.*}"

    if [[ "$A" != "$1" && "$B" != "$2" && "$A" == "$B" ]]
    then
        min_version "${1#*.}" "${2#*.}"
    else
        if is_number "$A" && is_number "$B"
        then
            [[ "$A" -ge "$B" ]]
        else
            [[ ! "$A" < "$B" ]]
        fi
    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

我希望这对某些人有用(使用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

这里一个有用的技巧是字符串索引。

$ echo "${BASH_VERSION}"
4.4.23(1)-release

$ echo "${BASH_VERSION:0:1}"
4

另一种方法(@joynes的修改版本)比较问题中问到的虚线版本 (即“1.2”、“2.3.4”、“1.0”、“1.10.1”等)。 最大数量的位置必须事先知道。该方法期望最多3个版本位置。

expr $(printf "$1\n$2" | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -g | sed -n 2p) != $2

使用示例:

expr $(printf "1.10.1\n1.7" | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -g | sed -n 2p) != "1.7"

返回:1,因为1.10.1大于1.7

expr $(printf "1.10.1\n1.11" | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -g | sed -n 2p) != "1.11"

返回:0,因为1.10.1比1.11低