【发布时间】:2011-04-26 21:34:41
【问题描述】:
在shell脚本中,将一个变量赋值给另一个变量时,这两者有什么区别:
a=$b
和
a="$b"
我什么时候应该使用一个而不是另一个?
【问题讨论】:
-
U&L Stack Exchange 上的相关帖子:Are quotes needed for local variable assignment?.
在shell脚本中,将一个变量赋值给另一个变量时,这两者有什么区别:
a=$b
和
a="$b"
我什么时候应该使用一个而不是另一个?
【问题讨论】:
我认为这里没有太大区别。是的,建议在引用该变量时用双引号将变量括起来。但是,$x 似乎没有在您的问题中被引用。
y=$x 本身不会影响空格的处理方式。只有在实际使用$y 时,引用才有意义。例如:
$ x=" a b "
$ y=$x
$ echo $y
a b
$ echo "$y"
a b
【讨论】:
当单独用作语句时,没有(很好的)理由将变量赋值的 RHS 双引号。
赋值语句的 RHS 不受分词(或大括号扩展)等的影响,因此不需要引号来正确赋值。所有其他扩展(据我所知)确实发生在 RHS 上,但也出现在双引号中,因此引用没有任何意义。
话虽如此,有理由不引用 RHS。即how to address error "bash: !d': event not found" in Bash command substitution(具体看我的回答和rici的回答)。
【讨论】:
来自 POSIX shell 语法规范的section 2.9.1:
每个变量赋值都应在赋值之前进行波浪号扩展、参数扩展、命令替换、算术扩展和引号删除。
字符串拆分和通配符(双引号抑制的步骤)不在此列表中。
因此,引号在所有简单赋值中都是多余的(这里不是针对那些使用declare、export 或类似命令的参数实现的),除了那些(1)单引号的行为,而不是双引号带引号的,需要字符串;或 (2) 值中的空格或其他内容将被解析为语法而不是文字。
(请注意,关于如何解析命令的决定——因此,无论是赋值、简单命令、复合命令还是其他命令——发生在 之前参数扩展;因此,在考虑 $1 的值之前,var=$1 被确定为赋值!如果这是不真实的,这样数据可以默默地变成语法,这将更加困难——如果不是不可能的话——在 bash 中编写处理不受信任数据的安全代码)。
【讨论】:
以下是一些其他示例:(在当前目录中有两个文件t.sh 和file)
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"..
【讨论】:
a="$(ls)"和a=$(ls)是否不同,而不是echo "$a"和echo $a是否不同。
Advanced Bash-Scripting Guide: Chapter 5: Quoting
当引用一个变量时,它是 通常建议附上其 双引号中的名称。这可以防止 重新诠释所有特殊 引用字符串中的字符。 使用双引号防止单词 分裂。一个参数包含在 双引号将自己呈现为 单个单词,即使它包含 空格分隔符。
【讨论】: