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

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

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

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

しかし、BusyBoxでは動作しません:(

sh: 1: [[: not found

ビジボックスに入るIFステートメントでは、ANDまたはORの組み合わせが機能しないようです。

答え1

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

busybox shashこれはPOSIX仕様のサブセット(POSIXロケール内でほとんど互換性があります)を実装し、sh特にこの拡張ではない拡張はほとんどありません。

2019年編集。使用して構築するときbusybox ashは今[[...]]kshだけでなく 。ASH_TESTASH_BASH_COMPATyash

それにもかかわらず、スクリプトを書くときはshPOSIX仕様に従う必要があります。sh使用されるスクリプトは[[...]]呼び出されるか、ksh明示的bashzsh呼び出される必要があります。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
    

これで、変数が次のようになっていることを確認したい場合があります。置く(null以外の場合と逆)、逆参照する前にオプションが有効になっている場合nounsetset -uまたはshe-bang行で使用)、そうでない場合はaが設定されていない場合はシェルが終了します。これを行うには、次の操作を行う必要があります。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。インタラクティブに実行されると、初期化を読み取​​ったファイルのパスとして扱われます(~/.bashrcforと同じbash)。他の目的に使用しないでください。

文字列比較の使用[ "x$var" = xproduction ]または実行を提案する古いUnixシェルスクリプト文書を見つけることができます。これは、akaユーティリティのいくつかの以前のバージョンで、またはなどの特定の値によって混乱するバグを[ production = "$var" ]克服するためのものです。最新のシステムではこれを必要としませんが、非常に古いシステムでは心に留めておくべきことです。とにかく、この構成にはそのような問題はありません。[test$var!(-ncase

文字列比較を実行できる他のPOSIXユーティリティには、およびがexprありますawk

 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

文字列比較(それ以外の場合はorと同じように処理されます)を取得し、同じ理由で演算子としての値に問題が発生しないようにするには、""値の前にwithが必要です。awk1011e0xexprexpr

awkand expr(少なくともPOSIXly)の場合、実際にはそうではありません。平等演算子は、代わりに両方のオペランドが同じソート順序を持つかどうかをテストします。これは必ずしも同じではありません。たとえば、私のシステムでは、expr_equal ② ③②と③の両方に定義されたソート順序がないため、trueが返されます。いくつかのawk実装(たとえばgawkmawkbusybox)はawkPOSIX要件を無視し、代わりに単純なバイト間比較を実行します。

[とにかく、私はあなたがここよりもこれを好むどんな妥当な理由も考えることができませんcase

答え2

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

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

-n(読みやすくなるので代わりに使っていますが、! -z同じです。)

または、文字列に値を指定して前の構文に単純化することもできます。

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

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

if [ "$ENV" = 'production' ]

関連情報