嘿伙计我有这个脚本应该确保用户当前的PHP版本在一定范围之间,虽然它应该工作,但是某个地方有一个错误让它认为版本超出范围,有人可能会一看,告诉我我能做些什么来解决它?
function version { echo "$@" | gawk -F. '{ printf("%d.%d.%d\n", $1,$2,$3); }'; }
phpver=`php -v |grep -Eow '^PHP [^ ]+' |gawk '{ print $2 }'`
if [ $(version $phpver) > $(version 5.2.13) ] || [ $(version $phpver) < $(version 5.2.13) ]; then
echo "PHP Version $phpver must be between 5.2.13 - 5.3.15"
exit
fi
答案 0 :(得分:63)
以下是比较版本的方法。
使用sort -V
:
function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
示例用法:
first_version=5.100.2
second_version=5.1.2
if version_gt $first_version $second_version; then
echo "$first_version is greater than $second_version !"
fi
亲:
缺点:
sort
,但您可能无法使用它
系统。 (查看man sort
) 没有sort -V
:
## each separate version number must be less than 3 digit wide !
function version { echo "$@" | gawk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }'; }
示例用法:
first_version=5.100.2
second_version=5.1.2
if [ "$(version "$first_version")" -gt "$(version "$second_version")" ]; then
echo "$first_version is greater than $second_version !"
fi
亲:
缺点:
关于您的脚本的评论:
我看不出它是如何起作用的:
>
和<
中所述的-gt
和-lt
5.5.9-1ubuntu4
。但是你的函数version()
已经非常巧妙地编写了并且可以通过规避经典问题来帮助你,即按字母顺序排序数字不会对数字进行数字排序(按字母顺序排列1 <11 <2,这在数字上是错误的) 。但要小心:bash不支持任意大数(如果你的目标是与32位系统兼容,那么试着保持在32位以下,这样就是9位长的数字)。所以我修改了你的代码(在第二种方法中不使用sort -V
),只对版本字符串的每个部分强制使用3位数。
编辑:应用@phk改进,因为它明显更聪明,并使用sort
删除第一个版本中的子进程调用。感谢。
答案 1 :(得分:10)
有可能进行deb分布:
dpkg --compare-versions <version> <relation> <version>
例如:
dpkg --compare-versions "0.0.4" "gt" "0.0.3"
if [ $? -eq "0" ]; then echo "YES"; else echo "NO"; fi
答案 2 :(得分:2)
正在进行词汇比较。使用其中一个:
if [ $(version $phpver) -gt $(version 5.2.13) ] || [ $(version $phpver) -lt $(version 5.2.13) ]; then
if [[ $(version $phpver) > $(version 5.2.13) ]] || [[ $(version $phpver) < $(version 5.2.13) ]]; then
if (( $(version $phpver) > $(version 5.2.13) )) || (( $(version $phpver) < $(version 5.2.13) )); then
或者在awk或其他工具中完成所有操作。它正在为一些优化而尖叫。你似乎也没有制作数字,所以你有一个非常奇怪的设计。通常版本子串乘以1000然后总计得到一个可比较的标量。
答案 3 :(得分:2)
以下是另一种解决方案:
tr
之外,请注意它是使用数组变量的Bash代码。
compare_versions()
{
local v1=( $(echo "$1" | tr '.' ' ') )
local v2=( $(echo "$2" | tr '.' ' ') )
local len="$(max "${#v1[*]}" "${#v2[*]}")"
for ((i=0; i<len; i++))
do
[ "${v1[i]:-0}" -gt "${v2[i]:-0}" ] && return 1
[ "${v1[i]:-0}" -lt "${v2[i]:-0}" ] && return 2
done
return 0
}
该函数返回:
然而#1 - 它需要一个额外的功能(但函数min
无论如何都非常有用):
min()
{
local m="$1"
for n in "$@"
do
[ "$n" -lt "$m" ] && m="$n"
done
echo "$m"
}
然而#2 - 它无法将版本字符串与字母数字部分进行比较(尽管实际上并不难添加)。
答案 4 :(得分:1)
以下解决方案应更准确地满足您的确切需求。它可用于测试CURRENT
版本字符串是否介于MIN
和MAX
之间。我假设MIN
和MAX
是可接受的版本号(即MIN <= CURRENT <= MAX
而不是MIN < CURRENT < MAX
)。
# Usage: version MIN CURRENT MAX
version(){
local h t v
[[ $2 = "$1" || $2 = "$3" ]] && return 0
v=$(printf '%s\n' "$@" | sort -V)
h=$(head -n1 <<<"$v")
t=$(tail -n1 <<<"$v")
[[ $2 != "$h" && $2 != "$t" ]]
}
例如......
if ! version 5.2.13 "$phpver" 5.3.15; then
echo "PHP Version $phpver must be between 5.2.13 - 5.3.15"
exit
fi
答案 5 :(得分:1)
如果您使用较旧版本的sort
使用旧版本的Bash 3(看看您的macOS ...),那么我创建了您可以输入的以下帮助程序脚本(也可以作为命令):
答案 6 :(得分:1)
测试PHP CLI版本的一个更安全的选择是使用PHP自己的version_compare
函数。
#!/bin/bash
MIN_VERSION="7.0.0"
MAX_VERSION="7.1.4"
PHP_VERSION=`php -r 'echo PHP_VERSION;'`
function version_compare() {
COMPARE_OP=$1;
TEST_VERSION=$2;
RESULT=$(php -r 'echo version_compare(PHP_VERSION, "'${TEST_VERSION}'", "'${COMPARE_OP}'") ? "TRUE" : "";')
test -n "${RESULT}";
}
if ( version_compare "<" "${MIN_VERSION}" || version_compare ">" "${MAX_VERSION}" ); then
echo "PHP Version ${PHP_VERSION} must be between ${MIN_VERSION} - ${MAX_VERSION}";
exit 1;
fi
echo "PHP Version ${PHP_VERSION} is good!";
答案 7 :(得分:0)
前一段时间,我写了这个不起眼的函数来解决类似的问题。如果arg1小于或等于arg2, vers_limit 将返回0,否则返回非0:
vers_limit()
{
VERNEW=$1
VERLMT=$2
CHKNEW=$VERNEW
CHKLMT=$VERLMT
PASSED=
while :
do
PARTNEW=${CHKNEW%%.*}
PARTLMT=${CHKLMT%%.*}
if [[ $PARTNEW -lt $PARTLMT ]]
then
PASSED=GOOD
break
elif [[ $PARTNEW -gt $PARTLMT ]]
then
PASSED=
break
else
NXTNEW=${CHKNEW#*.}
if [[ $NXTNEW == $CHKNEW ]]
then
if [[ $NXTNEW == $CHKLMT ]]
then
PASSED=GOOD
break
else
NXTNEW=0
fi
fi
NXTLMT=${CHKLMT#*.}
if [[ $NXTLMT == $CHKLMT ]]
then
NXTLMT=0
fi
fi
CHKNEW=$NXTNEW
CHKLMT=$NXTLMT
done
test "$PASSED"
}
尽管我相信有人可以对参数进行排序,解释通过/失败状态,但它不像这里的其他一些解决方案那样紧凑,也没有提供三向状态(即,更少,相等,更大)。和/或拨打两次以完成任何所需的结果。也就是说, vers_limit 确实具有某些优点:
不调用外部实用程序,例如sort,awk,gawk,tr等。
处理任意大小的数字版本(取决于shell的大小) 整数计算的限制)
处理任意数量的“点状”部分。
答案 8 :(得分:0)
v_min="5.2.15"
v_max="5.3.15"
v_php="$(php -v | head -1 | awk '{print $2}')"
[ ! "$v_php" = "$(echo -e "$v_php\n$v_min\n$v_max" | sort -V | head -2 | tail -1)" ] && {
echo "PHP Version $v_php must be between $v_min - $v_max"
exit
}
这会将v_min
,v_max
和v_php
按版本顺序放置,并测试v_php
是否不在中间。
答案 9 :(得分:0)
由于遇到相同的问题,我找到了进入此页面的方式。其他答案使我不满意,因此我编写了此函数。
只要两个版本中的句点数相同,就会正确比较两个版本。
它执行c样式的循环,将$ i从0递增地设置为版本字符串中的#号。
每个#:
如果是新的-旧的是否定的,我们知道第一个版本是新的。
如果新版本-旧版本是pos,我们知道第一个版本是旧版本。
如果new-old为0,那么它是相同的,我们需要继续检查。
在$ 1 == $ 2版本完全相同的情况下,我们在设置函数的退出状态后运行false。
newver=1.10.1
installedver=1.9.25
#installedver=1.11.25
#installedver=1.10.1
checkupdate(){
# $1 = new version
# $2 = installed version
IFS='.' read -r -a nver <<< "$1"
IFS='.' read -r -a iver <<< "$2"
for ((i = 0 ; i < "${#nver[@]}" ; i++)) ;do
case "$((${nver[i]}-${iver[i]}))" in
-*) return 1 ;;
0) ;;
*) return 0 ;;
esac
false
done
}
checkupdate "$newver" "$installedver" && echo yes || echo no
尝试在Android上实现上述功能后,我意识到我不会总是使用bash,因此上述功能对我而言不起作用。这是我使用awk编写的版本,以解决需要bash的问题:
checkupdate(){
# $1 = new version
# $2 = installed version
i=1
#we start at 1 and go until number of . so we can use our counter as awk position
places=$(awk -F. '{print NF+1}' <<< "$1")
while (( "$i" < "$places" )) ;do
npos=$(awk -v pos=$i -F. '{print $pos}' <<< "$1")
ipos=$(awk -v pos=$i -F. '{print $pos}' <<< "$2")
case "$(( $npos - $ipos ))" in
-*) return 1 ;;
0) ;;
*) return 0 ;;
esac
i=$((i+1))
false
done
}