当前位置:  开发笔记 > 编程语言 > 正文

如何比较Bash中点分隔版本格式的两个字符串?

如何解决《如何比较Bash中点分隔版本格式的两个字符串?》经验,为你挑选了10个好方法。

有没有办法比较的庆典,如这样的字符串:2.4.52.82.4.5.1



1> Paused until..:

这是一个纯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'


https://www.gnu.org/licenses/license-list.html#ccbysa`请不要将它用于软件或文档,因为它与GNU GPL`不兼容:/但是代码为+1
@KamilDziedzic:许可条款在本页底部(以及大多数其他人)中说明.
现在看起来不错 我撤回了我的反对意见.
这将失败'1.4rc2> 1.3.3'。注意字母数字版本

2> kanaka..:

如果你有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


好的解决方案 对于Mac OSX用户,您可以使用GNU Coreutils gsort.这可以通过自制软件获得:`brew install coreutils`.然后应该修改上面的内容以使用gsort.
GNU`sort`也具有`-C`或`--check = silent`,因此您可以编写`verlte(){printf'%s \ n%s'“ $ 1”“ $ 2” | 排序-C -V}`; 并严格检查小于,更简单地通过`verlt(){!verlte“ $ 2”“ $ 1”}`。
最好使用`printf`而不是`echo -e`.
在嵌入式Linux系统上不能与例如Busybox一起使用,因为[Busybox`sorting`](http://www.busybox.net/downloads/BusyBox.html#sort)没有`-V`选项.

3> Helmut Grohn..:

可能没有普遍正确的方法来实现这一目标.如果您正在尝试比较Debian软件包系统中的版本,请尝试dpkg --compare-versions .


用法:`dpkg --compare-versions"1.0""lt""1.2"`表示1.0小于1.2.如果为真,比较结果`$?`是'0`,所以你可以在`if`语句之后直接使用它.

4> mouviciel..:

GNU sort有一个选项:

printf '2.4.5\n2.8\n2.4.5.1\n' | sort -V

得到:

2.4.5
2.4.5.1
2.8


在嵌入式Linux系统上不能与例如Busybox一起使用,因为[Busybox`sorting`](http://www.busybox.net/downloads/BusyBox.html#sort)没有`-V`选项.
问题似乎是关于版本排序.考虑:`echo -e"2.4.10 \n2.4.9"| 排序-n -t
用数字排序这是不对的.您至少需要首先规范化字符串.

5> joynes..:

好吧,如果你知道你可以使用的字段数-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


派对迟到了四年,但到目前为止我最喜欢的解决方案:)

6> fakedrake..:

这适用于版本中最多4个字段.

$ function ver { printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' ' '); }
$ [ $(ver 10.9) -lt $(ver 10.10) ] && echo hello  
hello


如果版本也可以有5个字段,上面可以像这样安全:`printf"%03d%03d%03d%03d"$(echo"$ 1"| tr'.''\n'| head -n 4)`
不确定它是否适用于所有版本的bash,但在我的情况下,在最后一轮括号后缺少分号.
但它不适用于"10.09".

7> yairchu..:
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)


这个优于仅使用上面提出的默认bash printf.它正确处理像"1.09"这样的版本,普通printf无法处理,因为"09不是正确的数字".它还会自动删除前导零,这很有用,因为有时前导零会导致比较错误.

8> dogbane..:

您可以递归拆分.并进行比较,如下面的算法所示,取自此处.如果版本相同则返回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"

资源



9> Hachi..:

如果只是想知道一个版本是否低于另一个版本,我会检查是否sort --version-sort更改了版本字符串的顺序:

    string="$1
$2"
    [ "$string" == "$(sort --version-sort <<< "$string")" ]



10> v0rtex..:

我实现了一个函数,该函数返回与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
}

推荐阅读
赛亚兔备_393
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有