間接拡張内のパラメータの置き換え

間接拡張内のパラメータの置き換え

間接拡張内でパラメータ置換を実装したいのですが、単一のコマンドではこれを行うことはできません。 「無効な置換」エラーが発生します。この問題を解決するための賢明な方法があるかどうかを教えてください。

したがって、最初の変数の値を解析し、それを間接拡張で参照するために追加のコマンドを使用する必要があります。

最初の変数値を解析するための追加のコマンドなしで、単一のコマンドでこれをどのように実行できますか?

$ export first="hello"
$ export second_hello="finally"
$ echo ${second_${first}}
bash: ${second_${first}}: bad substitution 
$ echo ${!second_${first}}
bash: ${!second_${first}}: bad substitution
$ temp=second_${first}
$ echo ${!temp}
finally

temp文字列を取得するために追加の変数を使用することを避けたいと思いますfinally

答え1

bash中間変数が必要です。

first=hello
second_hello=finally
intermediary=second_$first
printf '%s\n' "${!intermediary}"

次の標準的な方法では、いつでもこれを行うことができますeval

eval 'printf "%s\n" "${second_'"$first"'}"'

私たちはこれを順番に andprintf "%s\n" "${second_hello}"に渡します。これは、別の引数としておよびを使用して呼び出されるシェルコードとして解釈されます。分割+グローブを防ぐには、外部コードと内部コードの引用符を参照してください。evalevalprintf%s\nfinally

bashzsh では、 's と同様にパラメータ拡張フラグを適用して、中間変数なしで拡張を適用できるという${!var}ことです。${(P)var}P${:-text}

first=hello
second_hello=finally
printf '%s\n' ${(P)${:-second_$first}}

または、eパラメーター拡張フラグを使用してください。

printf '%s\n' ${(e):-\$second_$first}

$firstこれらの方法はすべて、変数名に有効な文字のみが含まれていることが保証されている場合は同じように安全であり、そうでなければ同じように安全ではありません(任意のコマンド実行の脆弱性を導入)。したがって、値が外部に提供されている場合は、値を削除する必要があります$first。スクリプト。

ここでは、連想配列の使用を検討することができます。

typeset -A second
second[hello]=finally
first=hello
printf '%s\n' "${second[$first]}"

exportただし、環境変数は単に文字列/スカライズなので、連想配列変数を使用することはできません。しかし、これらの変数をエクスポートしたいとは思いません。マニュアルページを見つける場所を知るためにMANPATHコマンドをエクスポートしてインポートするのと同じように、実行したいコマンドによって「インポートされた」変数だけをエクスポートしたいと思います。man

答え2

中間変数を使わずにこれを見つけました。

[cloudshell-user@ip-10-0-25-104 ~]$ first=hello
[cloudshell-user@ip-10-0-25-104 ~]$ second_hello=finally
[cloudshell-user@ip-10-0-25-104 ~]$ eval echo \$second_$first
finally

関連情報