是否可以使用间接设置变量?

Ser*_*nev 8 bash

例如,下一个脚本将Hello由于${!规则而打印。

A=B
B=Hello
echo ${!A}
Run Code Online (Sandbox Code Playgroud)

但是如何设置为具有间接名称的变量?直接使用!符号不起作用:

A=B
!A=Hello # here is tricky line
echo $B
Run Code Online (Sandbox Code Playgroud)

我知道使用临时文件有一个技巧,但我对使用间接感兴趣,而不是像

A=B
echo "$A=Hello" > 1.tmp
. 1.tmp
echo $B
Run Code Online (Sandbox Code Playgroud)

Mat*_*Mat 13

您可以使用typeset内置函数执行此操作:

$ A=B
$ typeset $A=42
$ echo $B
42
Run Code Online (Sandbox Code Playgroud)

或使用declare

$ declare $A=1
$ echo $B
1
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 8

获取变量的值时遵循间接......

便携方式是使用eval. 您必须注意引用,以便在不应该评估值中的特殊字符时不会对其进行评估。最简单的方法是将新值存储在中间变量中并分配该变量的值。

A=B
tmp='stuff with special characters or whatever…'
eval $A=\$tmp
Run Code Online (Sandbox Code Playgroud)

的参数evalB=$tmp,一个简单的赋值。$tmp即使它包含空格或通配符,您也不需要双引号,因为它们不会在赋值中扩展。

如果要创建环境变量,可以使用export. 在 bash 或 ksh 或 zsh 中,您可以使用typeset来创建局部变量(declare在 bash 中是同义词)。同样,您应该使用一个中间变量,这样特殊字符就不会被破坏。请注意,除了在 zsh 中,您需要在变量扩展周围加上双引号,因为这不是一个赋值,而是一个内置函数,它接受一个恰好看起来像一个赋值的参数。

export $A="$tmp"
Run Code Online (Sandbox Code Playgroud)


Scr*_*zer 6

您可以尝试的另一种方法:

$ A=B
$ read $A <<< 81
$ echo "$B"
81
Run Code Online (Sandbox Code Playgroud)

但是存在安全风险 (!) 与所有这些方法一样(还有declare/typeset和当然eval).. 在这种情况下,必须控制左侧( 的值$A),换句话说,至少在 中bash,变量$A不应包含用户控制的输入,例如输入文件等...


如果您的 shell 不支持 here-string ( <<<),您也可以使用 here-document 代替:

A=B
read $A << EOF
82
EOF
echo "$B"
Run Code Online (Sandbox Code Playgroud)

  • shell 在读取命令之前扩展变量 $A.. (2认同)
  • 这不是一个好方法。它很复杂,如果值中有特殊字符(换行符、反斜杠和行上的前导或尾随空格有问题),它就会中断。 (2认同)