猿问

bash中的间接变量分配

似乎建议在bash中进行间接变量设置的推荐方法是使用eval:


var=x; val=foo

eval $var=$val

echo $x  # --> foo

问题是通常的问题eval:


var=x; val=1$'\n'pwd

eval $var=$val  # bad output here

(由于建议在很多地方使用,因此我想知道有多少脚本容易受到此攻击...)


在任何情况下,使用(转义)引号的明显解决方案实际上都不起作用:


var=x; val=1\"$'\n'pwd\"

eval $var=\"$val\"  # fail with the above

问题是bash在(with ${!foo})中包含了间接变量引用,但是我看不到任何这样的方法来进行间接赋值-是否有理智的方法来做到这一点?


作为记录,我确实找到了解决方案,但这并不是我认为的“理智” ...:


eval "$var='"${val//\'/\'\"\'\"\'}"'"


慕的地8271018
浏览 469回答 3
3回答

慕尼黑5688855

避免使用可能带来的安全隐患的一种更好的方法eval是declare "$var=$val"请注意,这declare是typesetin 的同义词bash。该typeset命令得到更广泛的支持(ksh并且zsh也可以使用它):typeset "$var=$val"在的现代版本中bash,应使用nameref。declare -n var=xx=$val它比更加安全eval,但仍然不够完美。

慕容森

Bash有一个扩展printf,可以将其结果保存到变量中:printf -v "${VARNAME}" '%s' "${VALUE}"这样可以防止所有可能的转义问题。如果您对使用无效的标识符$VARNAME,该命令将失败并返回状态代码2:$ printf -v ';;;' foobar; echo $?bash: printf: `;;;': not a valid identifier2

慕姐8265434

eval "$var=\$val"的参数eval应始终是用单引号或双引号引起来的单个字符串。在极端情况下,所有偏离此模式的代码都具有某些意外行为,例如带有特殊字符的文件名。当evalshell扩展参数to时,将$var其替换为变量名,并将其\$替换为一个简单的美元。因此,评估的字符串变为:varname=$value这正是您想要的。通常,所有形式的表达式都$varname应该用双引号引起来。只有两个地方可以省略引号:变量赋值和case。由于这是变量分配,因此此处不需要引号。不过,它们不会受到伤害,因此您也可以将原始代码编写为:eval "$var=\"the value is $val\""
随时随地看视频慕课网APP
我要回答