在 POSIX 脚本中,x=$y 是否始终等于 x="$y"?

fin*_*oot 9 scripting shell-script posix variable assignment

x=$y
Run Code Online (Sandbox Code Playgroud)

x="$y"
Run Code Online (Sandbox Code Playgroud)

总是等价的?不知道如何寻找这个。到目前为止,我一直习惯于x="$y"“安全起见”。但我x=$1曾经使用过并注意到,显然,我什至不需要额外的双引号。

The Open Group POSIX 文档中定义的行为在哪里?

Kus*_*nda 11

是的,x=$y并且x="$y"保证在 POSIX shell 中是相同的。如果您或代码的其他读者不确定在哪里必须使用双引号(请参阅何时需要双引号?),包括双引号可能是更安全的选择,以免引起混乱。

根据 POSIX 规范(第 2.9.1 节“简单命令”):

当需要执行给定的简单命令时[...],以下扩展、赋值和重定向都将从命令文本的开头到结尾执行:

  1. 根据Shell 语法规则识别为变量赋值或重定向的单词将被保存以便在步骤 3 和 4 中进行处理。

[...]

  1. 重定向应按照重定向中的描述执行。
  2. 每个变量赋值都应在赋值之前进行扩展,以进行波形符扩展、参数扩展、命令替换、算术扩展和引号删除。

请注意,第四点不包括字段拆分路径名扩展(“globbing”),它们通常是当单词不被识别为变量赋值时完成的扩展的一部分。由于分配时删除了这些步骤,因此不需要引用。

另请参见第 2.6 节“单词扩展”

单词扩展的顺序如下:

  1. 应从头到尾执行波形符扩展(请参阅波形符扩展)、参数扩展(请参阅参数扩展)、命令替换(请参阅命令替换)和算术扩展(请参阅算术扩展)。请参阅令牌识别中的第 5 项。
  2. 字段拆分(请参阅字段拆分)应在步骤 1 生成的字段部分上执行,除非IFS为 null。
  3. 除非有效,否则应执行路径名扩展(请参阅路径名扩展)。set -f
  4. 报价删除(请参阅报价删除)应始终最后执行。

y仅当inx=$y和实际上是特殊参数orx="$y"之一时,以下内容才重要:*@

请注意,由于"$@"扩展为字符串列表,因此未指定做什么x=$@x="$@"做什么,而 whilex=$*与 相同x="$*"。在某些 shell 中(例如bash, ksh93),这样的使用与的第一个字符是空格时$@的使用相同,而在其他 shell(例如 busybox , , )中,它与的设置值的第一个字符相同并使用。$*$IFSshdashzsh$*$IFS