为什么bash变量扩展保留引号?


12
> echo "hi"
hi
> VAR='echo "hi"'
> $VAR
"hi"

为什么上述命令的输出不同?

单引号也会发生类似的情况:

> VAR="echo 'hi'"
> $VAR
> 'hi'

6
请不要养成在变量中嵌入可执行脚本片段的习惯。这最好似乎很难,并且eval是潜在安全漏洞的雷区,您必须非常小心
jw013 2012年

@ jw013好点,很棒的文章。我喜欢引用“变量保存数据,函数保存代码”。从第一个链接开始,但就我的使用而言,提供给函数(在本例中为at)的数据代码。有什么技巧可以安全地组织/收集代码at
科里·克莱因

atsh语法作为输入。因此,生成输入at意味着sh从任意输入生成有效的,正确引用的语法,这并非微不足道,因此,我将尽可能避免使用它。如果您可以提供更多有关要完成的目标的详细信息,那将真正有帮助。
jw013

抱歉,我不想分散太多细节,但是IMO,我所做的并不是很复杂。我正在创建一个需要“时间”和“消息”的脚本。然后at,它会在给定的“时间” at内运行,并告诉您运行命令dzen2dzen2从标准输入中获取“消息”,还使用其他一些静态参数。困难在于我需要将用户的“ message”参数传递到dzen2命令中,但是我实际上并没有在运行dzen2自己,而是在告诉我at这样做。
科里·克莱因

Answers:


16

额外的一对报价只能通过额外的评估步骤来使用。例如eval

bash-4.2$ VAR='echo "hi"'

bash-4.2$ $VAR
"hi"

bash-4.2$ eval $VAR
hi

但是将带有参数的命令放在一个字符串中通常是一个坏主意。改用数组:

bash-4.2$ VAR=(echo "hi")

bash-4.2$ "${VAR[@]}"
hi

1
同样重要的是要注意报价的计算方式不同。双引号(“),允许封闭式串的评价,单引号(')打印字符串作为文字例:"$(ls)"'$(ls)'这就是为什么报价出现在原来的问题的例子的原因。
约瑟夫·科恩

数组也是问题的根源。代码属于函数,数据属于变量。您提供的示例仅适用于数组拆分中的引号。A printf '<%s> ' "${VAR[@]}"将显示引号已被删除。如果将VAR设置为VAR=(echo \"hi\")实际上有引号,则将再次出现相同的问题,$ ${VAR[@]}将显示"hi"

9

引号删除仅在原始输入单词上发生,而不在扩展结果上发生。扩展变量中的引号保持不变。


2

如果您退后一步,可以看到为什么变量替换绝对应保留引号。

Unix / Linux / BSD shell中的引号是将字符串的各个部分放在一起,否则它们将被解析为多个字符串。由于默认情况下,shell使用空格作为令牌分隔符,因此如果没有引号或以某种方式对其进行转义,则带空格的字符串(例如“一二三”)将被解析为3个字符串:“一”,“二”和“三”。

如果程序员想要一个内插一些变量值的字符串:

VAR=two
STRING="one $VAR three"

外壳绝对不应删除引号:包含空格的字符串将被解析为3个较小的字符串。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.