我应该在环境路径名中使用引号吗?

Cab*_*oup 24 bash shell dotfiles

我正在清理所有配置文件,试图使它们尽可能可读.我一直在寻找关于在导出路径时使用引号的样式指南,例如,~/.bashrc文件:

export PATH="/users/me/path:$PATH"
Run Code Online (Sandbox Code Playgroud)

VS

export PATH=/users/me/path:$PATH
Run Code Online (Sandbox Code Playgroud)

Google shell样式指南建议避免使用路径名称的引号.相比之下,许多流行的dotfiles回购(如Zach Holman在这里)使用引号.在路径中使用引号是否有利?

mkl*_*nt0 21

@gniourf_gniourf@chepner提供帮助.

TL;博士

为了安全起见,双引号:它适用于所有类似POSIX的shell.

如果要添加~基于路径的路径,请选择性地保留~/ 未加引号以确保~扩展; 例如:export PATH=~/"bin:$PATH". 请参阅下文,了解~变量赋值中的扩展规则.
或者,只需$HOME在单个双引号字符串中使用:
export PATH="$HOME/bin:$PATH"


注意:以下内容适用于bash,kshzsh,但不适用于(大多数)严格遵守POSIX的shell,例如dash; 因此,当你瞄准时/bin/sh,你必须加倍引用RHSexport.[1]

  • 双引号是可选的,只要你的RHS 的文字部分(要分配的值)既不包含空格也不包含其他shell元字符.
  • 无论是值引用变量包含空格/元字符或不也没有关系-见下文.
    • 再说一次:它确实很重要sh,何时export使用,所以总是双引号.

你能逃脱没有双引号在这种情况的原因是变量赋值在POSIX般的炮弹发言解释他们的RHS 不同的参数传递给命令,如在第2.9.1节的POSIX规范的:

  • 具体地讲,即使最初的字分裂进行,但仅适用于未展开的(原始)RHS(这就是为什么你带空格/元字符需要引用文字),而不是其结果.

  • 仅适用于所有类似POSIX的shell 中的表单的真正赋值语句
    <name>=<value>
    ,即,如果变量名称之前没有命令名称; 请注意,这包括为命令添加前缀的分配,例如,为其定义ad-hoc环境变量foo=$bar cmd ....

  • 为了安全起见,在其他命令的上下文中的赋值应始终是双引号:

    • sh(在(大部分)严格符合POSIX标准壳如dash)与分配export被视为常规命令,并且foo=$bar部分被视为第一参数export内置和因此处理照常(视的字分割结果也是).
      (POSIX不指定涉及(显式)可变分配的任何其它命令; declare,typeset,和local是非标准的扩展).

    • bash,ksh,zsh,在从POSIX可理解的偏差,延长分配逻辑export foo=$bartypeset/declare/local foo=$bar为好.换句话说:bash,ksh,zsh,export/typeset/declare/local命令被处理的像分配,以便引用不是严格必需的.

      • 也许令人惊讶的是dash,它也选择实现 -POSIX local内置[2] ,并没有将赋值逻辑扩展到它; export然而,它与其行为是一致的.
    • 传递给env(例如env foo=$bar cmd ...)的作业也可以作为命令参数进行扩展,因此需要双引号 - 除了zsh.

      • env行为不同于exportkshbash在这方面是由于这样的事实,env是一个外部工具,而export是一个shell内建.
        (当涉及到不带引号的变量引用时,(其zsh行为从根本上不同于其他shell 的行为).
  • Tilde(~)扩展在真正的赋值语句中如下所示:

    • 除了~需要不引用之外,像往常一样,它也只适用于:
      • 如果整个 RHS是~; 例如:
        • foo=~ # same as: foo="$HOME"
      • 否则:满足以下两个条件时:
        • 如果~启动字符串或前面有一个不带引号 :
        • 如果~后面是一个不带引号的 /.
        • 例如,
          foo=~/bin # same as foo="$HOME/bin"
          foo=$foo:~/bin # same as foo="$foo:$HOME/bin"

这个例子表明,在bash,kshzsh你能逃脱没有双引号,即使使用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'
Run Code Online (Sandbox Code Playgroud)

[1] @gniourf_gniourf指出:使用export修改的值PATH是可选的,因为一旦一个变量被标记为导出,可以使用常规的分配(PATH=...)来改变它的值.
也就是说,您仍然可以选择使用export,以便明确表达要修改的变量.

[2] @gniourf_gniourf声明POSIX标准的未来版本可能会引入local内置版本.


Fra*_*con 8

在 docker .env 文件中设置环境路径名时,我使用了上面的这些答案,并得到了一点。我把它放在这里供其他任何人寻找如何为 docker 定义环境变量。

Docker compose 从 .env 文件中读取环境变量,该文件位于运行 docker compose 的同一文件夹中,如此处所述https://docs.docker.com/compose/env-file。

但是,docker compose 不需要将值括在引号中,而是需要定义不带引号的环境变量,除非引号是值的一部分。同样,如上面的网址中所述

没有对引号进行特殊处理(即它们将成为 VAL 的一部分,您已被警告;)

我试图设置NODE_PATH=./src绝对路径以在 docker 部署的 React 应用程序中工作,但已将其编写为NODE_PATH="./src". 这个警告把我从 4 小时的兔子洞里拉了出来。