38

ユーザーの現在の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
4

10 に答える 10

103

バージョンを比較する方法は次のとおりです。

使用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

プロ:

  • ファンシーなバージョン文字列を比較する確かな方法:
    • 任意の長さのサブパーツをサポート (つまり: 1.3alpha.2.dev2 > 1.1 ?)
    • アルファベット順のソートをサポート (例: 1.alpha < 1.beta2)
    • 大きなサイズのバージョンをサポート (例: 1.10003939209329320932 > 1.2039209378273789273 ?)
  • n 引数をサポートするように簡単に変更できます。(演習として残しておきます ;) )
    • 通常、3 つの引数で非常に便利です: (つまり: 1.2 < my_version < 2.7 )

短所:

  • さまざまなプログラムへのさまざまな呼び出しを多数使用します。だから効率が悪いのです。
  • のかなり最近のバージョンを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

プロ:

  • 1つのサブプロセスのみを呼び出すため、より迅速なソリューション
  • はるかに互換性のあるソリューション。

短所:

  • 非常に具体的なバージョン文字列は次のようにする必要があります。
    • 1、2、または 3 パーツのみのバージョンがあります。(「2.1.3.1」を除く)
    • 各部分は数値のみでなければなりません (「3.1a」を除く)
    • 各部分は 999 を超えることはできません (「1.20140417」を除く)

スクリプトに関するコメント:

それがどのように機能するかわかりません:

  • コメントに記載されているように、>非常<に特別なシェル文字であり、それらを-gtおよびに置き換える必要があります-lt
  • 文字を置き換えたとしても、整数または浮動小数点数のようにバージョン番号を比較することはできません。たとえば、私のシステムでは、php のバージョンは5.5.9-1ubuntu4.

しかし、あなたの関数version()はすでに非常に巧妙に書かれており、数字をアルファベット順にソートしても数字が数字でソートされないという古典的な問題を回避するのに役立つかもしれません (アルファベット順で 1 < 11 < 2、これは数字的に間違っています)。ただし、注意してください: bash では、任意に大きな数値はサポートされていません (32 ビット システムとの互換性を目指す場合は、32 ビット未満に保つようにしてください。したがって、9 桁の長い数値になります)。sort -Vしたがって、バージョン文字列の各部分に 3 桁のみを強制するように(2 番目の方法では を使用せずに) コードを変更しました。

EDIT : @phk 改善を適用しました。これは、著しく賢く、最初のバージョンでsort. ありがとう。

于 2014-06-05T18:12:20.903 に答える
17

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
于 2017-09-19T12:03:46.263 に答える
4

字句比較を行っています。次のいずれかを使用します。

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 倍され、すべてが合計されて 1 つの比較可能なスカラーが取得されます。

于 2013-06-07T17:19:25.380 に答える
1

古いバージョンの Bash 3 を使用している場合sort(macOS を見てください...)、ソースとして使用できる次のヘルパー スクリプトを作成しました (コマンドとして実行することもできます)。

https://github.com/unicorn-fail/version_compare

于 2016-08-22T19:21:12.830 に答える
1

次のソリューションは、正確なニーズに正確に対応する必要があります。CURRENTバージョン文字列が ~ の間MINにあるかどうかをテストするために使用できますMAXMINMAXは許容可能なバージョン番号 (つまり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
于 2015-06-20T03:38:19.813 に答える
0

ピュアバッシュ

私は同じ問題を抱えていたので、このページにたどり着きました。他の答えは私を満足させなかったので、この関数を書きました。
2 つのバージョンのピリオドの数が同じである限り、バージョンが正しく比較されます。
ac スタイルの for ループを実行し、バージョン文字列で $i を 0 から # まで段階的に設定します。
#:
new - old が否定の場合、最初のバージョンの方が新しいことがわかります。
new - old が 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

SHの別の方法

上記の関数を Android に実装しようとした後、常に bash があるとは限らないことに気付きました。そのため、上記の関数は機能しませんでした。これは、bash が必要になるのを回避するために awk を使用して作成したバージョンです。

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
}
于 2020-05-16T12:03:56.000 に答える