変数の値を動的変数名として使用するには?

変数の値を動的変数名として使用するには?

この質問を見つけましたが、正しく質問する方法がわからないか、一般的な質問ではありません...

PHPでは、これは(ほぼ)マイナーなことです。

function getSite(string $prefix = 'prod') {
  $DEV_SITE='dev.site.com';
  $PROD_SITE='www.site.com';
  
  $site = strtoupper("{$prefix}_site");

  return ${$site};
}

getSite();      // www.site.com
getSite('dev'); // dev.site.com

じっくり実践してみましょう。

_SITE接尾辞付きの変数セットがあります。

DEV_SITE=dev.site.com
PROD_SITE=www.site.com

プレフィックスだけをパラメータとして使用してスクリプトを呼び出したいと思います。デフォルトは PROD です。

#!/bin/bash

PREFIX=${1:-PROD}

echo $PREFIX
---

$ script.sh dev
dev
$ script.sh
PROD

私の変数名の1つを取得する"_SITE"ために追加したいと思います。$PREFIX

VAR_NAME="${1:-PROD}_SITE"
echo $VAR_NAME
---

$ script.sh dev
dev_SITE
$script.sh
PROD_SITE

ああwww、dev_SITE無効ですが、発信者が違いを知る必要はありません。

devしたがって、変数名と一致するように変換されるように、パラメータを「大文字と小文字を区別しない」にしましょう。

SITE="${1:-PROD}_SITE"
# This does NOT work:
SITE="${1:-PROD^^}_SITE"
echo ${SITE^^}
---

$ script.sh dev
DEV_SITE
$script.sh
PROD_SITE

途方もない。しかし、最も簡単に入手できる方法は何ですか?その名前?

私が試したすべてのもので${SITE^^}「無効な置換」エラーが発生しました。

echo ${$SITE^^}_PROD
echo ${${!SITE^^}_PROD}
echo ${"${SITE^^}_PROD"}
echo ${"${!SITE^^}_PROD"}

など...

割り当てて再割り当てすると機能します。

SITE="${1:-PROD}_SITE"
SITE=${!SITE^^}
echo $SITE
---

$ script.sh dev
dev.site.com
$ script.sh
prod.site.com

私はこれがある段階ですべての代替操作を実行することに関連していると思いますが、サブシェルを使用して名前を別のコマンドにリンクしようとしましたが、理解できません。

答え1

あなたはそれを使用することができますnameref

現在bashのマンページから:

宣言またはローカル組み込みコマンドの-nオプション(以下の宣言とローカルの説明を参照)を使用して、変数にnameref属性を割り当てて、namerefまたは他の変数への参照を生成できます。これにより、変数を間接的に操作できます。 nameref変数が参照、割り当て、設定解除される、またはその属性が変更されるたびに(nameref属性自体を使用または変更する場合を除く)、実際には、nameref変数の値で指定された変数に対してアクションが実行されます。 nameref は通常、シェル関数の名前が関数に引数として渡される変数を参照するために使用されます。たとえば、変数名をシェル関数の最初の引数として渡す場合は、次のようにします。

         declare -n ref=$1

最初のパラメータとして渡された変数名を値として持つ関数内にnameref変数refを作成します。 refへの参照と割り当て、およびその属性への変更は、名前が$ 1に渡される変数への参照、割り当て、および属性の変更として扱われます。 forループの制御変数にnameref属性がある場合、単語リストはシェル変数リストになり、ループが実行されると、リスト内の各単語に名前参照が設定されます。 nameref属性は配列変数に割り当てることはできません。ただし、nameref変数は配列変数と添字配列変数を参照できます。 unset 組み込みコマンドの -n オプションを使用して Nameref の設定を解除できます。それ以外の場合、nameref変数の名前を引数としてunsetを実行すると、nameref変数が参照する変数がunsetされます。

これはnamerefを使用するスクリプトバージョンです。

#!/bin/bash

set -u

PROD_SITE='prod.example.com'
DEV_SITE='dev.example.com'
PREFIX=${1:-PROD}
SITEVAR=${PREFIX^^}_SITE

declare -n SITE=$SITEVAR

printf "Site is '%s'.\n" "${SITE}"

答え2

_SITE サフィックスが付いた変数セットがあります。

助けることができたらしないでください。可能であれば、連想配列(基本配列と似ていますが、インデックスは文字列です)を使用してください。これは以下を印刷しますwww.site.com

declare -A sites=([dev]=dev.site.com [prod]=www.site.com)
site=prod
echo "${sites[$site]}"

答え3

前述のように、Bashは逆参照ユーティリティ(「変数名と同じ値を提供する」)を提供するので、これは比較的簡単です。間違った選択をチェックすることは範囲外である可能性がありますが、set -u存在しない変数を使用すると、参照されるとスクリプトは中断されます。

$ ./625908.sh dev
Prefix is 'DEV'.
Site is 'dev.example.com'.
$ ./625908.sh fake
Prefix is 'FAKE'.
./625908.sh: line 9: !SITEVAR: unbound variable

したがって、このスクリプトを見てください。

#!/bin/bash
set -u
PROD_SITE='prod.example.com'
DEV_SITE='dev.example.com'
PREFIX=${1:-PROD}
PREFIX=${PREFIX^^} # Squash to uppercase
printf "Prefix is '%s'.\n" "${PREFIX}"
SITEVAR="${PREFIX}_SITE"
SITE="${!SITEVAR}"
printf "Site is '%s'.\n" "${SITE}"

これは少し簡単になるかもしれませんが、それほどではありません。

#!/bin/bash
set -u
PROD_SITE='prod.example.com'
DEV_SITE='dev.example.com'
PREFIX=${1:-PROD}
SITEVAR=${PREFIX^^}_SITE
SITE="${!SITEVAR}"
printf "Site is '%s'.\n" "${SITE}"

関連情報