我正在清理我的所有配置文件,以使它们尽可能可读。我一直在寻找关于在导出路径时使用引号的样式指南,例如,~/.bashrc
文件:
export PATH="/users/me/path:$PATH"
对比
export PATH=/users/me/path:$PATH
Google shell 样式指南建议避免路径名使用引号。相比之下,许多流行的 dotfiles 存储库(例如 Zach Holman 的此处)使用引号。在路径中使用引号是否有优势?
向@gniourf_gniourf和@chepner 致敬以寻求帮助。
tl;博士
为了安全起见,双引号:它适用于所有情况,适用于所有类似 POSIX 的 shell。
如果要添加~
基于 - 的路径,请选择性地保留~/
未引用的路径以确保~
扩展;例如:export PATH=~/"bin:$PATH"
。
变量赋值的扩展规则见下文。~
或者,只需$HOME
在单个双引号字符串中使用:
export PATH="$HOME/bin:$PATH"
注意:以下适用于bash
、ksh
和zsh
,但不适用于(大部分)严格符合 POSIX 的 shell,例如dash
; 因此,当您定位. 时/bin/sh
,您必须双引号export
. [1]
sh
export
在这种情况下你可以不用双引号就可以逃脱的原因是POSIX-like shell 中的变量赋值语句解释它们的 RHS与传递给commands的参数不同,如POSIX 规范的第 2.9.1 节所述:
具体来说,即使执行了初始分词,它也仅适用于未扩展的(原始)RHS(这就是为什么您需要在literals中使用空格/元字符引用),而不是其results。
这仅适用于所有类似 POSIX 的 shell中形式的真正赋值语句
<name>=<value>
,即,如果变量名之前没有命令名;请注意,这包括附加到命令以为其定义临时环境变量的分配,例如foo=$bar cmd ...
.
为了安全起见,其他命令上下文中的赋值应始终用双引号引起来:
对于sh
(在(大部分)严格符合 POSIX 的 shell 中,例如dash
),赋值 withexport
被视为常规命令,并且该foo=$bar
部分被视为内置函数的第一个参数,export
因此被视为通常处理(受结果,也是)。
(POSIX 没有指定任何其他涉及(显式)变量赋值的命令;declare
、、typeset
和local
是非标准扩展)。
bash
, ksh
, zsh
, 在与 POSIX 的一个可以理解的偏差中,将赋值逻辑扩展到export foo=$bar
和typeset/declare/local foo=$bar
。换句话说:in bash
, ksh
, zsh
,export/typeset/declare/local
命令被视为assignments,因此引用不是绝对必要的。
dash
,它也选择实现非-POSIXlocal
内置[2]
,并没有将分配逻辑扩展到它;然而,它与它的export
行为是一致的。传递给env
(例如,env foo=$bar cmd ...
)的赋值也可以作为命令参数进行扩展,因此需要双引号 - 除了 in zsh
。
env
行为不同是因为它是一个外部实用程序,而它是一个内置的 shell。
(在涉及未引用的变量引用时,其行为与其他 shell的行为根本不同)。export
ksh
bash
env
export
zsh
波浪号 ( ) 扩展在真正的赋值语句~
中发生如下:
~
需要被unquoted之外,像往常一样,它也只适用:
~
; 例如:
foo=~ # same as: foo="$HOME"
~
开始字符串或前面有一个不带引号的 :
~
后跟一个未引用 /
的.foo=~/bin # same as foo="$HOME/bin"
foo=$foo:~/bin # same as foo="$foo:$HOME/bin"
例子
这个例子展示了 in 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 指出的那样:使用 ofexport
来修改的值PATH
是可选的,因为一旦将变量标记为导出,您就可以使用常规赋值 ( PATH=...
) 来更改其值。
也就是说,您仍然可以选择使用export
,以便明确表示正在修改的变量已导出。
[2] @gniourf_gniourf 声明 POSIX 标准的未来版本可能会引入local
内置函数。
在 docker .env 文件中设置环境路径名时,我使用了上面的这些答案,并且有点。我把这个放在这里是为了给其他寻找如何为 docker 定义环境变量的人。
Docker compose 从 .env 文件中读取环境变量,该文件位于运行 docker compose 的同一文件夹中,如此处所述https://docs.docker.com/compose/env-file。
但是,docker compose 不需要将值包装在引号中,而是需要在没有引号的情况下定义环境变量,除非引号是值的一部分。同样,如上面的网址所述
引号没有特殊处理(即它们将成为 VAL 的一部分,您已被警告;)
我试图设置NODE_PATH=./src
绝对路径以在 docker 部署的反应应用程序中工作,但已将其编写为NODE_PATH="./src"
. 这个警告把我从 4 小时的兔子洞里拉了出来。
test 123
是 UNIX 上的有效路径名。尝试
PATH=test 123
它将返回:
123: command not found
甚至
export PATH=test 123
这将返回
bash export: `123': not a valid identifier
它回答了你的问题吗?
老实说,我不会遵循这样的第四方风格指南。虽然我很惊讶,即使是谷歌也宣传了这样的错误建议。
我会遵循:
(需谨慎扩展)