我应该在环境路径名中使用引号吗?
Should I use quotes in environment path names?
我正在清理我所有的配置文件,试图使它们尽可能可读。我一直在寻找关于在导出路径时使用引号的样式指南,例如 ~/.bashrc
文件:
export PATH="/users/me/path:$PATH"
对
export PATH=/users/me/path:$PATH
Google shell style guide suggests avoiding quotes for path names. In contrast, a lot of the popular dotfiles repos (such as Zach Holman's here) 使用引号。是否存在在路径中使用引号有优势的情况?
test 123
是 UNIX 上的有效路径名。尝试
PATH=test 123
会return:
123: command not found
甚至
export PATH=test 123
这将 return
bash export: `123': not a valid identifier
它是否回答了您的问题?
老实说,我不会遵循这样的第四方风格指南。虽然我很惊讶甚至 Google 宣传这样错误的建议。
我会关注:
- http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html
- http://www.tldp.org/LDP/abs/html/
- https://www.gnu.org/software/bash/manual/bash.html
(需慎重延伸)
向 @gniourf_gniourf and @chepner 致敬,寻求他们的帮助。
tl;dr
为了安全起见,双引号:它适用于所有情况,跨越所有 POSIX-like shells.
如果要添加基于 ~
的路径,有选择地 将 ~/
未加引号 保留为确保 ~
已展开;例如:export PATH=~/"bin:$PATH"
。
变量赋值~
扩展规则见下文
或者,只需在单个双引号字符串中使用 $HOME
:
export PATH="$HOME/bin:$PATH"
注意:以下内容适用于 bash
、ksh
和 zsh
,但严格来说(大部分)不适用于 POSIX 符合 shell 等 dash
;因此,当您定位 /bin/sh
时,您必须双引号 export
.[1]
- 双引号是 可选的,仅当 文字 部分是您的 RHS(要分配的值)既不包含空格也不包含其他 shell 元字符。
- 引用的变量的值是否包含whitespace/metacharacters与不无关紧要-见下文。
- 再说一遍: 与
sh
有关系,当使用 export
时,所以总是用双引号。
在这种情况下不用双引号就可以逃脱的原因是 变量赋值 语句在 POSIX-like shells 解释他们的 RHS 不同于 与 arguments 传递给 commands,如所述在 POSIX 规范的 section 2.9.1 中:
具体来说,即使初始分词是,它只应用于unexpanded (raw) RHS(这就是为什么你 do 需要在 literals 中用 whitespace/metacharacters 引用,和不是它的结果.
此仅适用于正版形式的赋值语句
<name>=<value>
in all POSIX-like shells,即如果没有no command name变量名前;请注意,这包括分配 prepended 到命令以为其定义临时环境变量,例如 foo=$bar cmd ...
.
赋值在其他命令的上下文中应该总是用双引号,为了安全:
与sh
(在(大部分)严格POSIX兼容的shell中,例如dash
)与[=23=的赋值] 被视为 常规命令 , foo=$bar
部分被视为 第一个参数 到 export
内置因此照常处理(也受 结果 的分词影响)。
(POSIX 没有指定涉及(显式)变量赋值的任何其他命令;declare
、typeset
和 local
是非标准的 扩展 ).
bash
、ksh
、zsh
,在与 POSIX 的可理解偏差中,将赋值逻辑扩展到 export foo=$bar
和typeset/declare/local foo=$bar
还有。换句话说:在bash
、ksh
、zsh
、export/typeset/declare/local
命令被视为assignments,所以引用不是绝对必要的.
- 也许令人惊讶的是,
dash
,它也选择了实现 non-POSIX local
builtin[2 ]
, 不向其扩展赋值逻辑;但是,它与其 export
行为一致。
传递给 env
的赋值(例如,env foo=$bar cmd ...
)也作为命令参数进行扩展,因此需要双引号 - 除了 zsh
.
env
在 ksh
和 bash
中的行为不同于 export
是因为 env
是 外部实用程序,而export
是shell内置.
(zsh
的行为 从根本上 与其他 shell 的行为在涉及未引用的变量引用时不同。
Tilde (~
) 扩展发生在 genuine 赋值语句:
- 除了
~
需要不加引号外,照例也只适用:
- 如果整个 RHS是
~
;例如。:
foo=~ # same as: foo="$HOME"
- 否则:仅如果两个满足以下条件:
- if
~
开始字符串或前面有 unquoted :
- if
~
后跟一个 unquoted /
.
- 例如
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
内置函数。
我在 docker .env 文件中设置环境路径名时使用了上面的这些答案,并且得到了位。我把它放在这里是为了其他任何正在寻找如何为 docker.
定义环境变量的人
Docker compose 从 .env 文件中读取环境变量,该文件存在于 docker compose 是 运行 的同一文件夹中,如此处所述 https://docs.docker.com/compose/env-file.
然而,docker compose 不需要将值用引号括起来,而是需要不带引号定义的环境变量,除非引号是值的一部分。同样,如上文url所述
There is no special handling of quotation marks (i.e. they will be
part of the VAL, you have been warned ;)
我试图为 docker 部署的 React 应用程序设置 NODE_PATH=./src
的绝对路径,但我将其写为 NODE_PATH="./src"
。这个警告把我从 4 小时的兔子洞里拉了出来。
我正在清理我所有的配置文件,试图使它们尽可能可读。我一直在寻找关于在导出路径时使用引号的样式指南,例如 ~/.bashrc
文件:
export PATH="/users/me/path:$PATH"
对
export PATH=/users/me/path:$PATH
Google shell style guide suggests avoiding quotes for path names. In contrast, a lot of the popular dotfiles repos (such as Zach Holman's here) 使用引号。是否存在在路径中使用引号有优势的情况?
test 123
是 UNIX 上的有效路径名。尝试
PATH=test 123
会return:
123: command not found
甚至
export PATH=test 123
这将 return
bash export: `123': not a valid identifier
它是否回答了您的问题?
老实说,我不会遵循这样的第四方风格指南。虽然我很惊讶甚至 Google 宣传这样错误的建议。
我会关注:
- http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html
- http://www.tldp.org/LDP/abs/html/
- https://www.gnu.org/software/bash/manual/bash.html
(需慎重延伸)
向 @gniourf_gniourf and @chepner 致敬,寻求他们的帮助。
tl;dr
为了安全起见,双引号:它适用于所有情况,跨越所有 POSIX-like shells.
如果要添加基于 ~
的路径,有选择地 将 ~/
未加引号 保留为确保 ~
已展开;例如:export PATH=~/"bin:$PATH"
。
变量赋值~
扩展规则见下文
或者,只需在单个双引号字符串中使用 $HOME
:
export PATH="$HOME/bin:$PATH"
注意:以下内容适用于 bash
、ksh
和 zsh
,但严格来说(大部分)不适用于 POSIX 符合 shell 等 dash
;因此,当您定位 /bin/sh
时,您必须双引号 export
.[1]
- 双引号是 可选的,仅当 文字 部分是您的 RHS(要分配的值)既不包含空格也不包含其他 shell 元字符。
- 引用的变量的值是否包含whitespace/metacharacters与不无关紧要-见下文。
- 再说一遍: 与
sh
有关系,当使用export
时,所以总是用双引号。
- 再说一遍: 与
在这种情况下不用双引号就可以逃脱的原因是 变量赋值 语句在 POSIX-like shells 解释他们的 RHS 不同于 与 arguments 传递给 commands,如所述在 POSIX 规范的 section 2.9.1 中:
具体来说,即使初始分词是,它只应用于unexpanded (raw) RHS(这就是为什么你 do 需要在 literals 中用 whitespace/metacharacters 引用,和不是它的结果.
此仅适用于正版形式的赋值语句
<name>=<value>
in all POSIX-like shells,即如果没有no command name变量名前;请注意,这包括分配 prepended 到命令以为其定义临时环境变量,例如foo=$bar cmd ...
.赋值在其他命令的上下文中应该总是用双引号,为了安全:
与
sh
(在(大部分)严格POSIX兼容的shell中,例如dash
)与[=23=的赋值] 被视为 常规命令 ,foo=$bar
部分被视为 第一个参数 到export
内置因此照常处理(也受 结果 的分词影响)。
(POSIX 没有指定涉及(显式)变量赋值的任何其他命令;declare
、typeset
和local
是非标准的 扩展 ).bash
、ksh
、zsh
,在与 POSIX 的可理解偏差中,将赋值逻辑扩展到export foo=$bar
和typeset/declare/local foo=$bar
还有。换句话说:在bash
、ksh
、zsh
、export/typeset/declare/local
命令被视为assignments,所以引用不是绝对必要的.- 也许令人惊讶的是,
dash
,它也选择了实现 non-POSIXlocal
builtin[2 ] , 不向其扩展赋值逻辑;但是,它与其export
行为一致。
- 也许令人惊讶的是,
传递给
env
的赋值(例如,env foo=$bar cmd ...
)也作为命令参数进行扩展,因此需要双引号 - 除了zsh
.env
在ksh
和bash
中的行为不同于export
是因为env
是 外部实用程序,而export
是shell内置.
(zsh
的行为 从根本上 与其他 shell 的行为在涉及未引用的变量引用时不同。
Tilde (
~
) 扩展发生在 genuine 赋值语句:- 除了
~
需要不加引号外,照例也只适用:- 如果整个 RHS是
~
;例如。:foo=~ # same as: foo="$HOME"
- 否则:仅如果两个满足以下条件:
- if
~
开始字符串或前面有 unquoted:
- if
~
后跟一个 unquoted/
. - 例如
foo=~/bin # same as foo="$HOME/bin"
foo=$foo:~/bin # same as foo="$foo:$HOME/bin"
- if
- 如果整个 RHS是
- 除了
例子
此示例演示了在 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
内置函数。
我在 docker .env 文件中设置环境路径名时使用了上面的这些答案,并且得到了位。我把它放在这里是为了其他任何正在寻找如何为 docker.
定义环境变量的人Docker compose 从 .env 文件中读取环境变量,该文件存在于 docker compose 是 运行 的同一文件夹中,如此处所述 https://docs.docker.com/compose/env-file.
然而,docker compose 不需要将值用引号括起来,而是需要不带引号定义的环境变量,除非引号是值的一部分。同样,如上文url所述
There is no special handling of quotation marks (i.e. they will be part of the VAL, you have been warned ;)
我试图为 docker 部署的 React 应用程序设置 NODE_PATH=./src
的绝对路径,但我将其写为 NODE_PATH="./src"
。这个警告把我从 4 小时的兔子洞里拉了出来。