if文と演算子で小数点を持つ数値を使用する

if文と演算子で小数点を持つ数値を使用する

条件と演算子を使用してLinuxオペレーティングシステムとバージョンを検出し、結果に応じて別のコマンドを実行するスクリプトを作成しようとしています。

オペレーティングシステムの検出

if [ -f /etc/os-release ]; then 
    . /etc/os-release 
    OS="$NAME" 
    OS_version="$VERSION_ID" 
elif [ -f /etc/debian_version ]; then 
    # Older Debian/Ubuntu/etc. 
    OS="Debian" 
    OS_version="$(cat /etc/debian_version)" 
fi

この変数をエコーすると返されます。

$ echo $OS 
Debian GNU/Linux

$ echo $OS_version 
10

以下の例では一致させたいと思います。ダーバンおよびオペレーティングシステムのバージョン10。しかし、$運営体制変数には単語以上の内容が含まれます。ダーバンしたがって、部分一致を実行するには一種のワイルドカードが必要です。

コマンドの置き換えで動作させる唯一の方法は、エコーすることです。$運営体制変数をstdoutに変換してgrepコマンドにパイプし、ワイルドカード検索を実行します。これは私が思いついたif文です。

if [ "$(echo "$OS" | grep 'Debian*')" -a "$OS_version" -ge 10 ]; then 
    echo "OS is Debian" 
    sleep 4 
else  
    echo "OS is other" 
    sleep 4 
fi

私はこのスクリプトを他のUnixベースのオペレーティングシステムで使用するので、このスクリプトをできるだけ広く互換性があり、POSIX標準に準拠したいと思います。

Ubuntu 21.04でスクリプトをテストしている間、Linuxでは、小数点以下の桁数が含まれている場合、どの数字が他の数字よりも大きいかを把握するのが難しいことがわかりました。以下では、2つの整数を小数点以下の2桁にエクスポートし、ifステートメントを使用して他の数より大きいか等しいかどうかを確認する2つのシェルスクリプトを作成しました。

20.10.sh

#!/bin/sh
export OS_version="20.10"

if [ "$OS_version" -ge 21.04 ]; then
    echo "Your OS is new enough"
    sleep 2
else
    echo "Your OS is too old!"
    sleep 2
fi

20.10.sh出力

~$ ./20.10.sh 
YOUR OS VERSION IS >> 20.10 
./20.10.sh: 6: [: Illegal number: 20.10 
Your OS is too old!

23.45.sh

#!/bin/sh
export OS_version="23.45" 
if [ "$OS_version" -ge 21.04 ]; then 
    echo "Your OS is new enough" 
    sleep 2 
else 
    echo "Your OS is too old!" 
    sleep 2 
fi

23.45.sh 出力

~$ ./23.45.sh 
YOUR OS VERSION IS >> 23.45 
./23.45.sh: 6: [: Illegal number: 23.45 
Your OS is too old!

これ23.45.shスクリプトは「あなたのオペレーティングシステムが十分に新しくなっています」とエコーする必要がありますが、エコーせずに誤った数字のエラーを表示します。

小数点以下の桁数で他の数字のサイズを検出する方法はありますか?

ベストアンサー1

標準[コマンドは数値比較演算子で10進整数のみをサポートします。一部[の実装([組み込み実装など)はksh93浮動小数点数と拡張をサポートしますが、これは移植性がなく、とにかく浮動小数点比較はバージョン比較と同じではありません。

たとえば、10.2浮動小数点数はより大きいが、バージョンとして解釈されるとその10.10逆になります。

Ubuntuのバージョンは日付です。 20.04(2020年4月)は20.10(2010年10月)以前です。これには、語彙比較を使用できます(willreach awk10を使用して実行できます)。

1.2pre5-beta1.21.2whileより小さいものは1.2a通常より大きいと見なされます1.2。バージョン命名規則がわからない場合は、バージョンを比較するのが難しいことがよくあります。

sortGNUシステムでは、GNUのアルゴリズムに従うこともできます--version-sort

version_greater_than() {
  local before_sort="$1"$'\n'"$2"
  [ "$before_sort" != "$(printf %s "$before_sort" | sort --stable --version-sort)" ]
}

(ksh93 / zsh / bash構文)またはそれにsh対応する構文:

version_greater_than() {
  [ "$1
$2" != "$(printf '%s\n' "$1" "$2" | sort --stable --version-sort)" ]
}

その後、次のことができます。

if version_greater_than 10.10 10.4; then
  echo 10.10 greater than 10.4
fi

awkPOSIXlyでは、任意の数値シーケンスを任意の長さでゼロで埋め、Cロケールで語彙比較を実行するアプローチをとることができます。

compare_versions() {
  LC_ALL=C awk -- '
    function pad(v,  ret) {
      while (match(v, /[0-9]+/)) {
        ret = ret substr(v, 1, RSTART - 1) \
              sprintf("%09d", substr(v, RSTART, RLENGTH))
        v = substr(v, RSTART + RLENGTH)
      }
      return ret v
    }
    BEGIN {exit !(pad(ARGV[1]) '"$2"' pad(ARGV[2]))}' "$1" "$3"
}

次のように使用されます。

if compare_versions 1.10 '>' 1.2; then
  echo '1.10 > 1.2'
fi

おすすめ記事