引用vs不引用变量赋值的RHS上的变量

时间:2010-10-18 11:32:48

标签: bash syntax quoting

在shell脚本中,将一个变量分配给另一个变量时,这两者之间有什么区别:

a=$b

a="$b"

什么时候应该使用一个而不是另一个?

5 个答案:

答案 0 :(得分:6)

我认为这里没有太大区别。是的,建议在引用该变量时将变量括在双引号中。但是,您的问题中似乎没有引用$x

y=$x本身不会影响如何处理空格。只有当$y实际使用时,引用才是重要的。例如:

$ x=" a    b "
$ y=$x
$ echo $y
a b
$ echo "$y"
 a    b

答案 1 :(得分:6)

当用作语句时,没有(好的)理由对变量赋值的RHS进行双重引用。

赋值语句的RHS不受分词(或括号扩展)等的影响,因此无需正确分配引号。所有其他扩展(据我所知)确实发生在RHS上,但也出现在双引号中,因此引用没有任何意义。

据说引用RHS的原因。即how to address error "bash: !d': event not found" in Bash command substitution(具体见我的回答和rici的回答)。

答案 2 :(得分:4)

来自POSIX shell语法规范的section 2.9.1

  

在分配值之前,应为代码扩展,参数扩展,命令替换,算术扩展和引用删除扩展每个变量赋值。

字符串拆分和通配(双引号抑制的步骤)不在此列表中。

因此,引号在所有简单赋值中都是多余的(这里不再说明那些使用declareexport或类似命令的参数实现的引号),除了那些(1)单引号的行为,而不是双引号,需要字符串;或(2)该值中的空格或其他内容将被解析为句法而非字面。

(注意,关于如何解析命令的决定 - 因此,无论是赋值,简单命令,复合命令还是其他 - 都在之前发生参数扩展;因此,var=$1被确定为在$1的值被考虑之前的赋值!如果这是不真实的,这样数据可以默默地变成语法,那将更加困难 - 如果并非不可能 - 在bash中编写处理不受信任数据的安全代码。)

答案 3 :(得分:2)

以下是其他一些示例:(在当前目录t.shfile中有两个文件)

a='$(ls)'        # no command substitution
b="$(ls)"        # command substitution, no word splitting
c='*'            # no filename expansion
d="*"            # no filename expansion
e=*              # no filename expansion
f=$a             # no expansions or splittings
g="$a"           # no expansions or splittings
h=$d             # no expansions or splittings

echo ---'$a'---
echo $a          # no command substitution
echo ---'$b'---
echo $b          # word splitting
echo ---'"$b"'---
echo "$b"        # no word splitting
echo ---'$c'---
echo $c          # filename expansion, word splitting
echo ---'"$c"'---
echo "$c"        # no filename expansion, no word splitting
echo ---'$d'---
echo $d          # filename expansion, word splitting
echo ---'"$d"'---
echo "$d"        # no filename expansion, no word splitting
echo ---'"$e"'---
echo "$e"        # no filename expansion, no word splitting 
echo ---'$e'---
echo $e          # filename expansion, word splitting
echo ---'"$f"'---
echo "$f"        # no filename expansion, no word splitting 
echo ---'"$g"'---
echo "$g"        # no filename expansion, no word splitting
echo ---'$h'---
echo $h          # filename expansion, word splitting
echo ---'"$h"'---
echo "$h"        # no filename expansion, no word splitting

输出:

---$a---
$(ls)
---$b---
file t.sh
---"$b"---
file
t.sh
---$c---
file t.sh
---"$c"---
*
---$d---
file t.sh
---"$d"---
*
---"$e"---
*
---$e---
file t.sh
---"$f"---
$(ls)
---"$g"---
$(ls)
---$h---
file t.sh
---"$h"---
*

有一件值得注意的事情是命令替换发生在变量赋值中,如果它们是双引号,并且RHS明确地给出为"$(ls)"而不是隐式赋予"$a" ..

答案 4 :(得分:1)

Advanced Bash-Scripting Guide: Chapter 5: Quoting

  

引用变量时,它是   通常建议将其封闭   用双引号命名。这可以防止   重新诠释所有特殊的   引用字符串中的字符。   使用双引号来防止单词   分裂。附上的参数   双引号表现为一个   单个单词,即使它包含   空白分隔符。