web-dev-qa-db-ja.com

変数の存在を確認し、busyboxの文字列と比較する方法は?

そのようなものを使いたい

if [[ ! -z "$ENV" && $ENV == 'production' ]]; then echo "production"; else echo "dev"; fi

しかしBusyBoxでは機能しません:(

sh: 1: [[: not found

ANDまたはORの組み合わせは、busyboxへのIFステートメントでは機能しません。

7
user1016265

古い[構文を使用できます

if [ -n "$ENV" -a "$ENV" = 'production' ]

(読みやすいので、-nではなく! -zを使用したことに注意してください。ただし、同じことです)。

または、文字列に値を強制することで、さらに古い構文に簡略化できます。

if [ "x$ENV" = 'xproduction' ]

最後に、-nテストは実際には必要ないかもしれません。

if [ "$ENV" = 'production' ]
6
Stephen Harris

[[...]]は、bashおよびzshでもサポートされているKornシェル構造ですが、標準のshのものではありません(他のシェルではサポートされていません)。

busyboxshは、ashのPOSIX仕様のサブセットを実装するshに基づいており(POSIXロケールでは、ほとんどの部分が準拠しており)、特に拡張機能はほとんどありません。

2019編集。 kshの[[...]]の限られたサブセットは、ASH_TESTASH_BASH_COMPAT、およびyashのはるかに大きなサブセットでビルドされた場合、busybox ashでもサポートされるようになりました。

いずれの場合でも、shスクリプトを作成するときは、POSIXのsh仕様に固執する必要があります。 [[...]]を使用するスクリプトは、kshbash、またはzshを明示的に呼び出す必要があります。 bashもまた、ほとんどがPOSIX sh互換のシェルですが、拡張機能が多くなっています(これを含む)。

xが空ではなく、productionと等しいかどうかのテストはほとんど意味がありません。 x== productionの場合、明らかに空ではありません。

POSIXシェルとユーティリティで文字列比較を行います。いくつかのオプションがあります。この場合の最も明白なオプションは次のとおりです。

  • [ユーティリティ(別名test)は、通常シェルに組み込まれています。

    if [ "$var" = production ]; then
      echo PROD
    fi
    
  • case構文:

    case $var in
      production) echo PROD;;
      "") echo EMPTY;;
      *) echo non-PROD;;
    esac
    

ここで、nounsetオプションが有効になっている場合に、変数を逆参照する前に、変数がsetであることを確認します(空ではない)。 set -uまたはset -o nounset、または#! /bin/sh -uをシバン行として使用)、そうでない場合、[ "$ENV" = production ]は、$ENVが設定されていない場合にシェルを終了します。それを行うには、次のようにします。

if [ "${var+set}" = set ] && [ "$var" = production ]; then
  echo PROD
fi

-a[ AND演算子は非推奨で信頼性が低いため、避けてください)。

それを行うためのより良い、より標準的な方法は次のとおりです。

if [ "${var-}" = production ]; then
  echo PROD
fi

nounsetは、${var+string}または${var-string}拡張ではトリガーされません。 ${var-}は、変数が設定されている場合は$varの内容に、それ以外の場合は空の文字列に展開されます。

その他の注意事項:

$ENVは、shの特殊変数です。対話的に開始すると、初期化を読み取​​るファイルへのパスとして使用されます(bash~/.bashrcに相当)。他の目的には使用しないでください。

一部の古いUnix Shellスクリプト記述では、[ "x$var" = xproduction ]または[ production = "x$var" ]を使用して文字列を比較することが推奨されています。これは、[$var!のような(のいくつかの値によって混乱した、-nおよびtestユーティリティのいくつかの古いバージョンのバグを克服するためです。最新のシステムでは必要ありませんが、非常に古いシステムでは注意が必要です。いずれの場合でも、case構成にはこの種の問題はありません。

文字列比較を実行できる他のPOSIXユーティリティには、exprawkがあります。

 awk_equal() { awk 'BEGIN{exit(!(""ARGV[1] == ""ARGV[2]))}' "$1" "$2"; }
 expr_equal() { expr "x $1" = "x $2" > /dev/null; }

 if awk_equal "$var" production; then
   echo PROD
 fi
 if expr_equal "$var" production; then
   echo PROD
 fi

awkの値の前に""を付加する必要があることに注意してください。そうしないと、文字列比較(そうでなければ101または1e0と等しいと見なされます)、およびxexprは、同じ理由でexpr演算子の値の問題を回避します。 。

awkexprの両方(少なくともPOSIXly)では、これらは実際にはequality演算子ではありませんが、2つのオペランドのソート順が等しいかどうかのテストであり、必ずしも同じではない場合があります。たとえば、5月のシステムでは、②も③もソート順が定義されていないため、expr_equal ② ③はtrueを返します。 awkgawk、busybox mawkなどの一部のawk実装は、POSIX要件を無視し、代わりに単純なバイト間比較を行います。

いずれにせよ、ここで[caseよりもそれらを好む理由は考えられません。

11