Eli*_*lay 34 bash quotes eval variable-assignment
似乎在bash中建议的间接变量设置方法是使用eval
:
var=x; val=foo
eval $var=$val
echo $x # --> foo
Run Code Online (Sandbox Code Playgroud)
问题是通常的问题eval
:
var=x; val=1$'\n'pwd
eval $var=$val # bad output here
Run Code Online (Sandbox Code Playgroud)
(并且因为在很多地方推荐,我想知道有多少脚本因此而易受攻击...)
在任何情况下,使用(转义)引号的明显解决方案并不真正起作用:
var=x; val=1\"$'\n'pwd\"
eval $var=\"$val\" # fail with the above
Run Code Online (Sandbox Code Playgroud)
问题是bash有(with ${!foo}
)烘焙的间接变量引用,但是我没有看到任何这种方式来做间接赋值 - 有没有理智的方法来做到这一点?
为了记录,我找到了解决方案,但这不是我认为"理智"的东西......:
eval "$var='"${val//\'/\'\"\'\"\'}"'"
Run Code Online (Sandbox Code Playgroud)
che*_*ner 28
一种稍微好一点的方法,避免使用可能带来的安全隐患eval
,是
declare "$var=$val"
Run Code Online (Sandbox Code Playgroud)
请注意,这declare
是typeset
in 的同义词bash
.该typeset
命令得到更广泛的支持(ksh
并且zsh
也使用它):
typeset "$var=$val"
Run Code Online (Sandbox Code Playgroud)
在现代版本中bash
,应该使用nameref.
declare -n var=x
x=$val
Run Code Online (Sandbox Code Playgroud)
它比eval
但更安全,但仍然不完美.
Dav*_*ter 27
Bash有一个扩展printf
,将结果保存到变量中:
printf -v "${VARNAME}" '%s' "${VALUE}"
Run Code Online (Sandbox Code Playgroud)
这可以防止所有可能的转义问题.
如果使用无效标识符$VARNAME
,命令将失败并返回状态代码2:
$ printf -v ';;;' foobar; echo $?
bash: printf: `;;;': not a valid identifier
2
Run Code Online (Sandbox Code Playgroud)
Rol*_*lig 18
eval "$var=\$val"
Run Code Online (Sandbox Code Playgroud)
参数to eval
应始终是用单引号或双引号括起来的单个字符串.偏离此模式的所有代码在边缘情况下都有一些意外行为,例如具有特殊字符的文件名.
当eval
shell扩展参数to时,将$var
替换为变量名,并\$
用简单的美元替换.因此,评估的字符串变为:
varname=$value
Run Code Online (Sandbox Code Playgroud)
这正是你想要的.
通常,表单的所有表达式都$varname
应该用双引号括起来.只有两个地方可以省略引号:变量赋值和case
.由于这是一个变量赋值,因此这里不需要引号.但是,他们不会受到伤害,因此您也可以将原始代码编写为:
eval "$var=\"the value is $val\""
Run Code Online (Sandbox Code Playgroud)
Eli*_*lay 11
重点是建议的方法是:
eval "$var=\$val"
Run Code Online (Sandbox Code Playgroud)
RHS间接完成了RHS.既然eval
在同一个环境中使用它,它就会$val
绑定,所以推迟它的工作,从现在起它只是一个变量.由于$val
变量具有已知名称,因此引用没有问题,甚至可以写为:
eval $var=\$val
Run Code Online (Sandbox Code Playgroud)
但是因为总是添加引号更好,前者更好,甚至更好:
eval "$var=\"\$val\""
Run Code Online (Sandbox Code Playgroud)
在整个事物中提到的bash中更好的替代方法是eval
完全避免(并且不像其他那样微妙declare
):
printf -v "$var" "%s" "$val"
Run Code Online (Sandbox Code Playgroud)
虽然这不是我最初要求的直接答案......
小智 6
较新版本的 bash 支持称为“参数转换”的内容,记录在 bash(1) 的同名部分中。
"${value@Q}"
扩展为 shell 引用的版本"${value}"
,您可以将其重新用作输入。
这意味着以下是一个安全的解决方案:
eval="${varname}=${value@Q}"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
30117 次 |
最近记录: |