是否有办法在bash上比较这些字符串,例如:2.4.5和2.8和2.4.5.1?
当前回答
GNU排序有一个选项:
printf '2.4.5\n2.8\n2.4.5.1\n' | sort -V
给:
2.4.5
2.4.5.1
2.8
其他回答
可能没有普遍正确的方法来实现这一点。如果您正在尝试比较Debian包系统中的版本,请尝试dpkg——compare-versions <first> <relation> <second>。
如果你知道字段的数量,你可以用-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
我使用嵌入式Linux (Yocto)与BusyBox。BusyBox排序没有-V选项(但BusyBox expr匹配可以做正则表达式)。所以我需要一个Bash版本的比较,它适用于这个约束。
我做了以下(类似于Dennis Williamson的回答)来比较使用“自然排序”类型的算法。它将字符串分成数字部分和非数字部分;它以数字方式比较数字部分(因此10大于9),并以纯ASCII方式比较非数字部分。
ascii_frag() {
expr match "$1" "\([^[:digit:]]*\)"
}
ascii_remainder() {
expr match "$1" "[^[:digit:]]*\(.*\)"
}
numeric_frag() {
expr match "$1" "\([[:digit:]]*\)"
}
numeric_remainder() {
expr match "$1" "[[:digit:]]*\(.*\)"
}
vercomp_debug() {
OUT="$1"
#echo "${OUT}"
}
# return 1 for $1 > $2
# return 2 for $1 < $2
# return 0 for equal
vercomp() {
local WORK1="$1"
local WORK2="$2"
local NUM1="", NUM2="", ASCII1="", ASCII2=""
while true; do
vercomp_debug "ASCII compare"
ASCII1=`ascii_frag "${WORK1}"`
ASCII2=`ascii_frag "${WORK2}"`
WORK1=`ascii_remainder "${WORK1}"`
WORK2=`ascii_remainder "${WORK2}"`
vercomp_debug "\"${ASCII1}\" remainder \"${WORK1}\""
vercomp_debug "\"${ASCII2}\" remainder \"${WORK2}\""
if [ "${ASCII1}" \> "${ASCII2}" ]; then
vercomp_debug "ascii ${ASCII1} > ${ASCII2}"
return 1
elif [ "${ASCII1}" \< "${ASCII2}" ]; then
vercomp_debug "ascii ${ASCII1} < ${ASCII2}"
return 2
fi
vercomp_debug "--------"
vercomp_debug "Numeric compare"
NUM1=`numeric_frag "${WORK1}"`
NUM2=`numeric_frag "${WORK2}"`
WORK1=`numeric_remainder "${WORK1}"`
WORK2=`numeric_remainder "${WORK2}"`
vercomp_debug "\"${NUM1}\" remainder \"${WORK1}\""
vercomp_debug "\"${NUM2}\" remainder \"${WORK2}\""
if [ -z "${NUM1}" -a -z "${NUM2}" ]; then
vercomp_debug "blank 1 and blank 2 equal"
return 0
elif [ -z "${NUM1}" -a -n "${NUM2}" ]; then
vercomp_debug "blank 1 less than non-blank 2"
return 2
elif [ -n "${NUM1}" -a -z "${NUM2}" ]; then
vercomp_debug "non-blank 1 greater than blank 2"
return 1
fi
if [ "${NUM1}" -gt "${NUM2}" ]; then
vercomp_debug "num ${NUM1} > ${NUM2}"
return 1
elif [ "${NUM1}" -lt "${NUM2}" ]; then
vercomp_debug "num ${NUM1} < ${NUM2}"
return 2
fi
vercomp_debug "--------"
done
}
它可以比较更复杂的版本号,例如
1.2-r3和1.2-r4 1.2 r3 vs 1.2r4
请注意,对于Dennis Williamson的回答中的一些极端情况,它不会返回相同的结果。特别是:
1 1.0 <
1.0 1 >
1.0.2.0 1.0.2 >
1..0 1.0 >
1.0 1..0 <
但这些都是极端情况,我认为结果仍然是合理的。
您可以通过版本命令行查看版本约束
$ version ">=1.0, <2.0" "1.7"
$ go version | version ">=1.9"
Bash脚本示例:
#!/bin/bash
if `version -b ">=9.0.0" "$(gcc --version)"`; then
echo "gcc version satisfies constraints >=9.0.0"
else
echo "gcc version doesn't satisfies constraints >=9.0.0"
fi
GNU排序有一个选项:
printf '2.4.5\n2.8\n2.4.5.1\n' | sort -V
给:
2.4.5
2.4.5.1
2.8