是否有办法在bash上比较这些字符串,例如:2.4.5和2.8和2.4.5.1?
当前回答
ver_cmp()
{
local IFS=.
local V1=($1) V2=($2) I
for ((I=0 ; I<${#V1[*]} || I<${#V2[*]} ; I++)) ; do
[[ ${V1[$I]:-0} -lt ${V2[$I]:-0} ]] && echo -1 && return
[[ ${V1[$I]:-0} -gt ${V2[$I]:-0} ]] && echo 1 && return
done
echo 0
}
ver_eq()
{
[[ $(ver_cmp "$1" "$2") -eq 0 ]]
}
ver_lt()
{
[[ $(ver_cmp "$1" "$2") -eq -1 ]]
}
ver_gt()
{
[[ $(ver_cmp "$1" "$2") -eq 1 ]]
}
ver_le()
{
[[ ! $(ver_cmp "$1" "$2") -eq 1 ]]
}
ver_ge()
{
[[ ! $(ver_cmp "$1" "$2") -eq -1 ]]
}
测试:
( ( while read V1 V2 ; do echo $V1 $(ver_cmp $V1 $V2) $V2 ; done ) <<EOF
1.2.3 2.2.3
2.2.3 2.2.2
3.10 3.2
2.2 2.2.1
3.1 3.1.0
EOF
) | sed 's/ -1 / < / ; s/ 0 / = / ; s/ 1 / > /' | column -t
1.2.3 < 2.2.3
2.2.3 > 2.2.2
3.10 > 3.2
2.2 < 2.2.1
3.1 = 3.1.0
ver_lt 10.1.2 10.1.20 && echo 'Your version is too old'
Your version is too old
其他回答
你们都给出了复杂的解决方案。这里有一个更简单的例子。
function compare_versions {
local a=${1%%.*} b=${2%%.*}
[[ "10#${a:-0}" -gt "10#${b:-0}" ]] && return 1
[[ "10#${a:-0}" -lt "10#${b:-0}" ]] && return 2
a=${1:${#a} + 1} b=${2:${#b} + 1}
[[ -z $a && -z $b ]] || compare_versions "$a" "$b"
}
用法:compare_versions <ver_a> <ver_b>
返回代码1表示第一个版本大于第二个版本,2表示小于第二个版本,0表示两者相等。
也是一个非递归的版本:
function compare_versions {
local a=$1 b=$2 x y
while [[ $a || $b ]]; do
x=${a%%.*} y=${b%%.*}
[[ "10#${x:-0}" -gt "10#${y:-0}" ]] && return 1
[[ "10#${x:-0}" -lt "10#${y:-0}" ]] && return 2
a=${a:${#x} + 1} b=${b:${#y} + 1}
done
return 0
}
如果你知道字段的数量,你可以用-k,n,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
我遇到并解决了这个问题,添加了一个额外的(更短更简单的)答案…
首先注意,扩展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
如果它只是想知道一个版本是否比另一个版本低,我会检查sort——version-sort是否会改变我的版本字符串的顺序:
string="$1
$2"
[ "$string" == "$(sort --version-sort <<< "$string")" ]
ver_cmp()
{
local IFS=.
local V1=($1) V2=($2) I
for ((I=0 ; I<${#V1[*]} || I<${#V2[*]} ; I++)) ; do
[[ ${V1[$I]:-0} -lt ${V2[$I]:-0} ]] && echo -1 && return
[[ ${V1[$I]:-0} -gt ${V2[$I]:-0} ]] && echo 1 && return
done
echo 0
}
ver_eq()
{
[[ $(ver_cmp "$1" "$2") -eq 0 ]]
}
ver_lt()
{
[[ $(ver_cmp "$1" "$2") -eq -1 ]]
}
ver_gt()
{
[[ $(ver_cmp "$1" "$2") -eq 1 ]]
}
ver_le()
{
[[ ! $(ver_cmp "$1" "$2") -eq 1 ]]
}
ver_ge()
{
[[ ! $(ver_cmp "$1" "$2") -eq -1 ]]
}
测试:
( ( while read V1 V2 ; do echo $V1 $(ver_cmp $V1 $V2) $V2 ; done ) <<EOF
1.2.3 2.2.3
2.2.3 2.2.2
3.10 3.2
2.2 2.2.1
3.1 3.1.0
EOF
) | sed 's/ -1 / < / ; s/ 0 / = / ; s/ 1 / > /' | column -t
1.2.3 < 2.2.3
2.2.3 > 2.2.2
3.10 > 3.2
2.2 < 2.2.1
3.1 = 3.1.0
ver_lt 10.1.2 10.1.20 && echo 'Your version is too old'
Your version is too old