bashでevalを使用してスペースを含む値を変数に割り当てる方法

bashでevalを使用してスペースを含む値を変数に割り当てる方法

変数に動的に値を割り当てたいですeval。次のダミーの例が機能します。

var_name="fruit"
var_value="orange"
eval $(echo $var_name=$var_value)
echo $fruit
orange

ただし、変数の値にスペースが含まれている場合、二重eval引用符の間にあってもエラーが返されます。$var_value

var_name="fruit"
var_value="blue orange"
eval $(echo $var_name="$var_value")
bash: orange : command not found

この問題を解決する方法はありますか?

答え1

体験版を使用しないでください。declare

$ declare "$var_name=$var_value"
$ echo "fruit: >$fruit<"
fruit: >blue orange<

答え2

evalこの目的には使用しないでくださいdeclare

var_name="fruit"
var_value="blue orange"
declare "$var_name=$var_value"

最初の単語だけでなく、それ以降のすべての項目が値と見なされる=ため、単語の分割は問題になりません。declare

4.3では、bash名前付き参照を使用すると、この操作がより簡単になります。

$ declare -n var_name=fruit
$ var_name="blue orange"
$ echo $fruit
blue orange

あなたできる作業してみましょうeval。しかし、それでもやってはいけません:)eval使用するのは悪い習慣です。

$ eval "$(printf "%q=%q" "$var_name" "$var_value")"

答え3

これを使用する良い方法はテストにeval置き換えることです。そして同じように動作します(特定の実装によって作成された拡張を除いて(たとえば、特定の条件下で))。echoechoeval\xechobash

どちらのコマンドもスペースを使用して引数を連結します。違いは次のとおりです。echo 見せる同時に結果eval 評価する/説明するシェルコードの結果。

それでは、どのシェルコードがあるのか​​見てみましょう。

eval $(echo $var_name=$var_value)

評価して以下を実行できます。

$ echo $(echo $var_name=$var_value)
fruit=blue orange

これはあなたが望むものではありません。あなたが望むものは次のとおりです。

fruit=$var_value

また、$(echo ...)ここで使用することは意味がありません。

上記を出力するには、以下を実行する必要があります。

$ echo "$var_name=\$var_value"
fruit=$var_value

だから簡単に説明すると、次のようになります。

eval "$var_name=\$var_value"

個々の配列要素の設定にも使用できます。

var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"

他の人が言ったように、コードが具体的であるかどうか気にしない場合は、bash次のことを使用できますdeclare

declare "$var_name=$var_value"

しかし、副作用もあるので注意してください。

変数の範囲を変数を実行する関数に制限します。したがって、次の状況では使用できません。

setvar() {
  var_name=$1 var_value=$2
  declare "$var_name=$var_value"
}
setvar foo bar

fooこれはローカル変数を宣言するので役に立ちsetvarません。

bash-4.2宣言する-gオプションが追加されました。declareグローバルsetvarしかし、それは私たちが望むものではありません。グローバル呼び出し元が関数の場合、varは呼び出し元のvarとは反対です。

setvar() {
  var_name=$1 var_value=$2
  declare -g "$var_name=$var_value"
}
foo() {
  local myvar
  setvar myvar 'some value'
  echo "1: $myvar"
}
foo
echo "2: $myvar"

すると、以下が出力されます。

1:
2: some value

またdeclare、呼び出されている間declare(実際にbashKornシェル組み込みの概念を借用するtypesetdeclare、変数がすでに設定されている場合、新しい変数は宣言されず、割り当ての実行方法は変数の種類によって異なります。

たとえば、

varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"

varname以前に次のように宣言された場合スカラー大量にまたは連想配列

また、コンテンツが厳密に管理されていないdeclareよりも安全ではありません。eval$varname

たとえば、eval "$varname=\$varvalue"とが含まれている場合は、両方ともdeclare "$varname=$varvalue"システムを再起動します。$varnamea[$(reboot)1]

答え4

死んだ参照を使用してください。アポストロフィ。
eval $(echo $var_name='$var_value')
それは私にとって効果的でした。

関連情報