是否有办法在bash上比较这些字符串,例如:2.4.5和2.8和2.4.5.1?
当前回答
这里一个有用的技巧是字符串索引。
$ echo "${BASH_VERSION}"
4.4.23(1)-release
$ echo "${BASH_VERSION:0:1}"
4
其他回答
如果你有coreutils-7 (Ubuntu Karmic,而不是Jaunty),那么你的排序命令应该有一个-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
function version_compare () {
function sub_ver () {
local len=${#1}
temp=${1%%"."*} && indexOf=`echo ${1%%"."*} | echo ${#temp}`
echo -e "${1:0:indexOf}"
}
function cut_dot () {
local offset=${#1}
local length=${#2}
echo -e "${2:((++offset)):length}"
}
if [ -z "$1" ] || [ -z "$2" ]; then
echo "=" && exit 0
fi
local v1=`echo -e "${1}" | tr -d '[[:space:]]'`
local v2=`echo -e "${2}" | tr -d '[[:space:]]'`
local v1_sub=`sub_ver $v1`
local v2_sub=`sub_ver $v2`
if (( v1_sub > v2_sub )); then
echo ">"
elif (( v1_sub < v2_sub )); then
echo "<"
else
version_compare `cut_dot $v1_sub $v1` `cut_dot $v2_sub $v2`
fi
}
### Usage:
version_compare "1.2.3" "1.2.4"
# Output: <
功劳归于@Shellman
这里是另一个没有任何外部调用的纯bash解决方案:
#!/bin/bash
function version_compare {
IFS='.' read -ra ver1 <<< "$1"
IFS='.' read -ra ver2 <<< "$2"
[[ ${#ver1[@]} -gt ${#ver2[@]} ]] && till=${#ver1[@]} || till=${#ver2[@]}
for ((i=0; i<${till}; i++)); do
local num1; local num2;
[[ -z ${ver1[i]} ]] && num1=0 || num1=${ver1[i]}
[[ -z ${ver2[i]} ]] && num2=0 || num2=${ver2[i]}
if [[ $num1 -gt $num2 ]]; then
echo ">"; return 0
elif
[[ $num1 -lt $num2 ]]; then
echo "<"; return 0
fi
done
echo "="; return 0
}
echo "${1} $(version_compare "${1}" "${2}") ${2}"
还有更简单的解决方案,如果你确定所讨论的版本在第一个点后不包含前导零:
#!/bin/bash
function version_compare {
local ver1=${1//.}
local ver2=${2//.}
if [[ $ver1 -gt $ver2 ]]; then
echo ">"; return 0
elif
[[ $ver1 -lt $ver2 ]]; then
echo "<"; return 0
fi
echo "="; return 0
}
echo "${1} $(version_compare "${1}" "${2}") ${2}"
这适用于像1.2.3 vs 1.3.1 vs 0.9.7这样的版本,但不适用于其他版本 1.2.3 vs 1.2.3.0或1.01.1 vs 1.1.1
可能没有普遍正确的方法来实现这一点。如果您正在尝试比较Debian包系统中的版本,请尝试dpkg——compare-versions <first> <relation> <second>。
当Bash变得太复杂时,就把它输送到python中!
vercomp(){ echo "$1" "$2" | python3 -c "import re, sys; arr = lambda x: list(map(int, re.split('[^0-9]+', x))); x, y = map(arr, sys.stdin.read().split()); exit(not x >= y)"; }
比较两个版本号的例子:
vercomp 2.8 2.4.5 && echo ">=" || echo "<"
这个python一行代码比较左边版本号和右边版本号,如果左边版本号等于或更高,则退出0。它还处理2.4.5rc3这样的版本
分解后,这是可读的代码:
import re, sys
# Convert a version string into a list "2.4.5" -> [2, 4, 5]
arr = lambda x: list(map(int, re.split('[^0-9]+', x)))
# Read the version numbers from stdin and apply the above function to them
x, y = map(arr, sys.stdin.read().split())
# Exit 0 if the left number is greater than the right
exit(not x >= y)