【发布时间】:2011-09-08 20:56:42
【问题描述】:
我正在尝试编写一个增加版本号的 bash 脚本
{major}.{minor}.{revision}
例如。
1.2.13
有没有一种好方法可以使用 sed 或 awk 之类的方法轻松提取这 3 个数字,这样我就可以增加 {revision} 数字并输出完整的版本号字符串。
【问题讨论】:
我正在尝试编写一个增加版本号的 bash 脚本
{major}.{minor}.{revision}
例如。
1.2.13
有没有一种好方法可以使用 sed 或 awk 之类的方法轻松提取这 3 个数字,这样我就可以增加 {revision} 数字并输出完整的版本号字符串。
【问题讨论】:
$ v=1.2.13
$ echo "${v%.*}.$((${v##*.}+1))"
1.2.14
$ v=11.1.2.3.0
$ echo "${v%.*}.$((${v##*.}+1))"
11.1.2.3.1
这是它的工作原理:
字符串被分成两部分。
${v%.*}
${v##*.}
第一部分按原样打印,后跟一个普通点,最后一部分使用 shell 算术扩展递增:$((x+1))
【讨论】:
使用数组的纯 Bash:
version='1.2.33'
a=( ${version//./ } ) # replace points, split into array
((a[2]++)) # increment revision (or other part)
version="${a[0]}.${a[1]}.${a[2]}" # compose new version
【讨论】:
IFS 并使用"${a[*]}"。谢谢,可以好好利用了!
我更喜欢这种事情的“剪切”命令
major=`echo $version | cut -d. -f1`
minor=`echo $version | cut -d. -f2`
revision=`echo $version | cut -d. -f3`
revision=`expr $revision + 1`
echo "$major.$minor.$revision"
我知道这不是最短的方法,但对我来说它是最容易理解和阅读的......
【讨论】:
另一种 shell 方式(表明总是有不止一种方式可以玩弄这些东西......):
$ echo 1.2.3 | ( IFS=".$IFS" ; read a b c && echo $a.$b.$((c + 1)) )
1.2.4
所以,我们可以这样做:
$ x=1.2.3
$ y=`echo $x | ( IFS=".$IFS" ; read a b c && echo $a.$b.$((c + 1)) )`
$ echo $y
1.2.4
【讨论】:
Awk 让它变得非常简单:
echo "1.2.14" | awk -F \. {'print $1,$2, $3'} 将打印出 1 2 14。
flag -F 指定分隔符。
如果您希望保存其中一个值:
firstVariable=$(echo "1.2.14" | awk -F \. {'print $1'})
【讨论】:
echo | awk 三次。
major.minor,这应该给它:echo "1.2.14" | awk -F \. '{version=$1"."$2; print version}' 将打印出1.2。
我使用shell自带的分词;像
oIFS="$IFS"
IFS=.
set -- $version
IFS="$oIFS"
尽管由于字母或日期后缀以及其他令人讨厌的不一致位,您通常需要小心使用版本号。之后,位置参数将设置为$version的组件:
$1 = 1
$2 = 2
$3 = 13
($IFS 是一组单个字符,而不是字符串,因此这不适用于多字符字段分隔符,尽管您可以使用 IFS=.- 在 . 或 - 上进行拆分。)
【讨论】:
$IFS 是shell用来进行自己的字段(“单词”)拆分的东西;我正在保存原始值(空格、制表符、换行符)并将其设置为.,然后使用set 强制$version 进行分词。我将扩展答案。
set -- $version 将命令行参数替换为按句点分隔的 $version 字段。因此,这三个部分现在是$1、$2、$3。如果你不想使用 set,你可以试试这个:echo $version | read major minor revision。它没有那么紧凑,但不会弄乱您可能仍在使用的命令行参数。
while 循环可能在子shell 中运行,可能会产生令人惊讶的结果(例如,循环中的变量设置不会被脚本的其余部分看到)。 stackoverflow.com/questions/6245246/…
while 行并将其删除。我没有超过一分钟。管道输入到 while 读取循环的旧习惯。实际上,我放的东西在 BASH 中不起作用,但在我使用的 Kornshell 中起作用。它与 BASH 完全兼容,除非它不是。为了让它在 bash 中工作,您必须将 $version 作为此处的文档。
受jlliagre 的回答启发,我制作了自己的版本它支持版本号,只需给出主要版本。 jlliagre 的版本会变成 1 -> 1.2 而不是 2。
这一款适用于两种版本号:
function increment_version()
local VERSION="$1"
local INCREMENTED_VERSION=
if [[ "$VERSION" =~ .*\..* ]]; then
INCREMENTED_VERSION="${VERSION%.*}.$((${VERSION##*.}+1))"
else
INCREMENTED_VERSION="$((${VERSION##*.}+1))"
fi
echo "$INCREMENTED_VERSION"
}
这将产生以下输出:
increment_version 1 -> 2
increment_version 1.2 -> 1.3
increment_version 1.2.9 -> 1.2.10
increment_version 1.2.9.101 -> 1.2.9.102
【讨论】:
使用内置read 命令将字符串拆分为数组的fgm 解决方案的小变化。请注意,IFS 变量的范围仅限于read 命令(因此无需存储和恢复当前的IFS 变量)。
version='1.2.33'
IFS='.' read -r -a a <<<"$version"
((a[2]++))
printf '%s\n' "${a[@]}" | nl
version="${a[0]}.${a[1]}.${a[2]}"
echo "$version"
【讨论】: