在shell脚本中比较两个版本号

piok6c0g  于 2023-01-26  发布在  Shell
关注(0)|答案(4)|浏览(377)

我有一个文件file1,如下所示,包含当前版本和预期版本号:

CurrV:1.5.2
ExpecV:1.8.1

我想编写一个bash脚本来比较这两个值,如果ExpecV>=CurrV,则应该echo SUCCESS,否则应该echo FAILURE
到目前为止,我已经写了这件事,但不确定如何进行:

#!/bin/bash
 ## Code already written to fetch `ExpecV` and `CurrV` from `file1`
 echo $ExpecV | grep $CurrV > /dev/null
 if [ $? -eq 0 ]
    then
        echo SUCCESS
    else
        echo FAILURE
 fi
fgw7neuy

fgw7neuy1#

你可以试试

if [ $(echo "${CurrV}\n${ExpecV}"|sort|head -1) != "${CurrV}" ]; then ...
vxqlmq5t

vxqlmq5t2#

这个问题说ExpecV>=CurrV应该被视为成功,但这没有多大意义(当前版本比预期版本旧,可能会破坏一些东西),在您对此答案的评论中,您暗示了所需的行为是相反的,所以这就是此答案所做的。
这需要为-V选项进行GNU排序(版本排序):

if cmp -s <(cut -d: -f2 infile) <(cut -d: -f2 infile | sort -V); then
    echo 'FAILURE'
else
    echo 'SUCCESS'
fi

这要求带有CurrV的行始终是第一行,它提取带有cut的冒号之后的部分,并将未排序的(第一个进程替换<(...))与版本排序的输出(第二个进程替换)进行比较。
如果相同,即第二行版本大于等于第一行版本,则cmp退出成功,打印FAILURE;如果它们不相同,这意味着sort颠倒了顺序,并且预期版本小于当前版本,因此我们打印SUCCESS
-s标志用于抑制cmp的输出(“静默”);我们只关心退出状态。
如果1.5.21.8.1已经位于单独的变量CurrVExpecV中,则可以执行类似的操作,如下所示:

CurrV='1.5.2'
ExpecV='1.8.1'
printf -v versions '%s\n%s' "$CurrV" "$ExpecV"
if [[ $versions = "$(sort -V <<< "$versions")" ]]; then
    echo 'FAILURE'
else
    echo 'SUCCESS'
fi

这将两个变量存储到versions中,用换行符分隔,然后比较未排序的序列和排序的序列。

k3bvogb1

k3bvogb13#

@benjamin-w和@Walter A的答案都非常简洁,我们也可以使用for循环逐个比较子版本的数值,如下所示:

#!/bin/bash
#
# given 2 version numbers:
# check if ExpecV>=CurrV: SUCCESS
#
CurrV=1.5.2
ExpecV=1.8.1

#
# here below:
#   xarr: array of split CurrV numerical elements
#   yarr: array of split ExpecV numerical elements
#   isnewer: key if version ExpecV is newer than or equal to CurrV
#
#
# use parameter expansion to replace dot by space,
# and then convert them to arrays:
#
xarr=(${CurrV//./ })
yarr=(${ExpecV//./ })
    
#
# suppose that ExpecV is newer (bigger) or equal to CurrV version:
#
isnewer=true

#
# loop over array keys:
#
for i in "${!xarr[@]}"; do
  #
  #printf '${xarr[%s]}=%s\n' $i ${xarr[i]}
  #printf '${yarr[%s]}=%s\n' $i ${yarr[i]}
  #
  #
  # compare sub-version values: break if not equal:
  #
  if [ ${yarr[i]} -gt ${xarr[i]} ]; then
    break
  elif [ ${yarr[i]} -lt ${xarr[i]} ]; then
    isnewer=false
    break
  fi
done

#
# show result:
#
if [ $isnewer == true ]; then
  echo "SUCCESS: $ExpecV is newer than or equal to $CurrV."
else
  echo "FAILURE: $ExpecV is not newer than or equal to $CurrV."
fi
g52tjvyc

g52tjvyc4#

如果您使用的是Debian系统,那么使用dpkg是最简单的:

if dpkg --compare-versions $A lt $B
then
  # $A < $B was true
fi

它支持所有六个比较运算符(参见man dpkg和在compare-versions上搜索)。
一个潜在的缺点:你的版本必须与Debian兼容。

相关问题