向@gniourf_gniourf 和@chepner 致敬以寻求帮助。
tl;dr
安全起见,双引号:它适用于所有情况,适用于所有类似 POSIX 的 shell。
如果要添加基于~ 的路径,有选择地保留~/ 未引用以确保~ 被扩展;例如:export PATH=~/"bin:$PATH"。
变量赋值中~扩展的规则见下文。
或者,只需在单个双引号字符串中使用 $HOME:
export PATH="$HOME/bin:$PATH"
注意:以下内容适用于 bash、ksh 和 zsh,但不适用于(大部分)严格符合 POSIX 标准的 shell,例如 dash;因此,当您定位 /bin/sh 时,您必须用双引号将 export 的 RHS 引用。[1]
- 双引号是可选,仅当您的 RHS 的 literal 部分(要分配的值)既不包含空格也不包含其他 shell 元字符时。强>
-
引用的变量的值是否包含空格/元字符不很重要 - 见下文。
- 再次重申:当使用
export 时,它确实与sh 有关,因此请始终在此处使用双引号。
在这种情况下你可以不用双引号就可以逃脱的原因是,在类似 POSIX 的 shell 中 variable-assignment 语句解释它们的 RHS 不同于 em>arguments 传递给 commands,如 POSIX 规范的section 2.9.1 中所述:
具体来说,即使执行 initial 分词,它也仅适用于 未扩展(原始)RHS (这就是为什么您确实需要在文字中用空格/元字符引用,而不是引用它的结果。
这仅适用于真正的形式的赋值语句
<name>=<value>在所有类似POSIX的shell,即,如果变量名前没有命令名;请注意,这包括为命令定义临时环境变量的分配前置,例如foo=$bar cmd ...。
-
为了安全起见,在其他命令的上下文中的赋值应始终用双引号:
对于sh(在(大部分)严格符合POSIX 的shell 中,例如dash),带有export 的赋值被视为常规命令,而@ 987654345@ 部分被视为export 内置函数的第一个参数,因此按常规处理(也受到结果的分词)。
(POSIX 没有指定任何其他涉及(显式)变量赋值的命令;declare、typeset 和 local 是非标准的扩展。
-
bash、ksh、zsh,在可以理解的与 POSIX 的偏差中,将赋值逻辑也扩展到 export foo=$bar 和 typeset/declare/local foo=$bar。换句话说:在bash、ksh、zsh、export/typeset/declare/local 中的命令被视为分配,因此引用并不是绝对必要的。
- 也许令人惊讶的是,
dash,它也选择实现 非-POSIX local 内置[2]
, 不会将赋值逻辑扩展到它;但是,它与其export 行为一致。
-
传递给env(例如env foo=$bar cmd ...)的分配也可以作为命令参数进行扩展,因此需要双引号 - zsh 除外。
-
env 在这方面与ksh 和bash 中的export 行为不同是因为env 是一个外部实用程序,而export 是shell 内置。
(zsh 的行为从根本上与其他 shell 在未引用变量引用方面的行为不同)。
-
波浪号 (~) 扩展在真正的赋值语句中发生如下:
- 除了
~ 需要不引用,像往常一样,它也只适用:
- 如果整个 RHS 是
~;例如。:
foo=~ # same as: foo="$HOME"
- 否则:仅如果满足以下条件两个:
- 如果
~ 开始字符串或前面有一个未引用 :
- 如果
~ 后跟一个未引用 /。
- 例如,
foo=~/bin # same as foo="$HOME/bin"
foo=$foo:~/bin # same as foo="$foo:$HOME/bin"
示例
这个例子表明,在bash、ksh 和zsh 中,即使使用export,您也可以不使用双引号,但我不这样做推荐它。
#!/usr/bin/env bash
# or ksh or zsh - but NOT /bin/sh!
# Create env. variable with whitespace and other shell metacharacters
export FOO="b:c &|<> d"
# Extend the value - the double quotes here are optional, but ONLY
# because the literal part, 'a:`, contains no whitespace or other shell metacharacters.
# To be safe, DO double-quote the RHS.
export FOO=a:$foo # OK - $FOO now contains 'a:b:c &|<> d'
[1] 正如@gniourf_gniourf 指出的那样:使用export 修改PATH 的值是可选的,因为一旦将变量标记为导出,您就可以使用用于更改其值的常规分配 (PATH=...)。
也就是说,您仍然可以选择使用export,以便明确表示正在修改的变量已导出。
[2] @gniourf_gniourf 指出,POSIX 标准的未来版本可能会引入 local 内置函数。