为什么在赋值`foo=$bar` 中不需要双引号`$bar`?

Tim*_*Tim 2 bash quoting assignment

来自https://unix.stackexchange.com/a/32227/674

不使用双引号是安全的主要地方是:

  • 在赋值中:(foo=$bar但请注意,您确实需要export "foo=$bar"在数组赋值中或数组赋值中 使用双引号array=("$a" "$b"));
  1. 这是否意味着不需要$bar在赋值中双引号foo=$bar?为什么?

  2. 为什么我们需要export "foo=$bar"像这样的数组赋值中的双引号array=("$a" "$b")

谢谢。

Sté*_*las 6

foo=$bar
Run Code Online (Sandbox Code Playgroud)

安全的,因为它是使用标量赋值语法的赋值和对标量变量的赋值。这是一个标量上下文,只能存储一个值$var, split 或 glob 没有意义$bar。如果扩展导致多个单词,shell 将需要以某种方式再次组合它们,以便能够将它们作为一个字符串存储在$foo.

当你使用时它是不同的:

foo=($bar)
Run Code Online (Sandbox Code Playgroud)

分配给数组变量的位置。这是一个列表上下文。您正在为数组元素分配一些单词。split+glob 发生。

还要注意某些 shell 中诸如export/ local/ typeset/ declare/ 之类的双重性质readonly(在局部变量赋值是否需要引号中有更详细的解释

你会注意到:

foo=$bar
Run Code Online (Sandbox Code Playgroud)

被解析为赋值,而

"foo"=$bar
Run Code Online (Sandbox Code Playgroud)

只是尝试运行foo=content_of_bar命令(其中 bar 的内容受 split+glob 影响)。

export(和其他local/ typeset...)既是关键字又是内置(ksh、bash 和 zsh 的最新版本)的 shell 中,在:

export foo=$bar
Run Code Online (Sandbox Code Playgroud)

export被识别为关键字foo=$bar赋值,因此$bar不受 split+glob 的约束。但它几乎export不需要停止被识别为关键字。在这种情况下,它只是被视为一个简单的命令, split+glob 就像在任何其他命令的任何参数中一样发生。

即使在 whereexport被视为关键字的情况下,如果参数看起来不像变量赋值("foo"=$bar如上所示),那么它们将被视为普通参数并再次受到 split+glob 的影响。