如何使用bash来修改版本号

时间:2010-12-19 22:11:24

标签: bash replace

我想知道如何使用bash来修改版本号中的最后一位数。

e.g。

VERSION=1.9.0.9
NEXT_VERSION=1.9.0.10

编辑:版本号只包含自然数。

解决方案是否可以通用,以处理版本号中的任意数量的部件。

e.g。

1.2
1.2.3
1.2.3.4
1.2.3.4.5

4 个答案:

答案 0 :(得分:8)

让我们从迈克尔的基本答案开始:

VERSIONS="
1.2.3.4.4
1.2.3.4.5.6.7.7
1.9.9
1.9.0.9
"

for VERSION in $VERSIONS; do 
    echo $VERSION | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g'
done

我们如何才能改善这一点?以下是从大量评论中提取的一堆想法。

程序中的尾随“1”对其操作至关重要,但它不是最明确的做事方式。最后的奇数'1'是一个布尔值,它是真的,因此匹配每一行并触发默认操作(因为后面的括号内没有动作),这是打印$ 0,行读取,修改为上一个命令。

因此,为什么不使用awk命令来避免sed命令?

awk -F. '{$NF+=1; OFS="."; print $0}'

当然,我们可以在几个阶段进一步改进。你可以使用bash'<<<<字符串重定向操作符以避免管道:

awk -F. '...' <<< $VERSION

接下来的观察是,给定一系列行,只需执行一次awk即可处理它们:

echo "$VERSIONS" | awk -F. '/[0-9]+\./{$NF+=1;OFS=".";print}'

没有for循环。 “$ VERSION”周围的双引号保留字符串中的换行符。管道仍然是不必要的,导致:

awk -F. '/[0-9]+\./{$NF+=1;OFS=".";print}' <<< "$VERSIONS"

正则表达式忽略$VERSION中的空行仅处理包含数字后跟点的行。当然,在每行中设置OFS有点笨拙,“+=1”可以缩写为“++”,因此您可以使用:

awk -F. '/[0-9]+\./{$NF++;print}' OFS=. <<< "$VERSIONS"

(或者你可以在程序中加入'BEGIN{OFS="."}',但这相当冗长。

'<<<'表示法仅由Bash支持,而不是由Korn,Bourne或其他POSIX shell支持(除非作为与Bash表示法并行的非标准扩展名)。任何版本的awk都可以支持AWK程序,但是旧的UNIX 7th Edition AWK不支持命令行上的变量赋值。

答案 1 :(得分:5)

我想出了这个。

VERSIONS="
1.2.3.4.4
1.2.3.4.5.6.7.7
1.9.9
1.9.0.9
"

for VERSION in $VERSIONS; do 
    echo $VERSION | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g'
done

答案 2 :(得分:2)

if [[ "$VERSION" == *.* ]]; then
    majorpart="${VERSION%.*}."
else
    majorpart=""
fi
minorpart="${VERSION##*.}"
NEXT_VERSION="$majorpart$((minorpart+1))"

警告:如果版本号的次要部分不是预期格式(整数,没有前导零),则可能有问题。一些例子:“1.033” - &gt; “1.28”(因为033是27的八进制),“1.2.b” - &gt; “1.2.1”(除非b是定义的变量,它将被视为0),“1.2.3a” - &gt;错误(“3a”不是数字)。根据您想要覆盖的案例数量,这可以是任意复杂的。

答案 3 :(得分:0)

好吧,Jonathan Leffler已经answered这个问题,但是我已经推广了接受任意差异(作为awk参数versionDiff传递)的解决方案:

VERSION="1.4.1.2"
awk -v versionDiff="0.1" -F. -f bump.awk OFS=. <<< "$VERSION"

结果将是:

1.5.0.0

因为上一个非零versionDiff编号之后的数字被清零。

bump.awk

/[0-9]+\./ {
  n = split(versionDiff, versions, ".")
  if(n>NF) nIter=n; else nIter=NF
  lastNonzero = nIter
  for(i = 1; i <= nIter; ++i) {
    if(int(versions[i]) > 0) {
      lastNonzero = i
    }
    $i = versions[i] + $i
  }
  for(i = lastNonzero+1; i <= nIter; ++i) {
    $i = 0
  }
  print
}