在 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。即如何在 Bash 命令替换中解决错误“bash:!d':未找到事件”(具体请参见我的答案和 rici 的答案)。
从POSIX shell 语法规范的第 2.9.1 节:
在分配值之前,每个变量分配都应针对波浪号扩展、参数扩展、命令替换、算术扩展和引号删除进行扩展。
字符串拆分和通配符(双引号抑制的步骤)不在此列表中。
因此,引号在所有简单赋值中都是多余的(这里不是指那些使用 参数 或类似命令实现的赋值) declare
,export
除了那些(1)需要单引号而不是双引号的字符串的行为;或 (2) 值中的空格或其他内容将被解析为语法而不是文字。
(请注意,关于如何解析命令的决定——因此,它是赋值、简单命令、复合命令还是其他东西——发生在参数扩展之前;因此,var=$1
在的值$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"
。
Advanced Bash-Scripting Guide: Chapter 5: Quoting
When referencing a variable, it is generally advisable to enclose its name in double quotes. This prevents reinterpretation of all special characters within the quoted string. Use double quotes to prevent word splitting. An argument enclosed in double quotes presents itself as a single word, even if it contains whitespace separators.