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

时间:2015-10-24 13:00:07

标签: bash shell dotfiles

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

export PATH="/users/me/path:$PATH"

vs

export PATH=/users/me/path:$PATH

Google shell style指南建议避免使用路径名称的引号。相比之下,很多流行的dotfiles回购(例如Zach Holman的here)都使用引号。在路径中使用引号是否有利?

3 个答案:

答案 0 :(得分:18)

@gniourf_gniourf@chepner求助的提示。

<强> TL;博士

为了安全起见,双引号:它可以在所有类似POSIX的shell中工作。

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

注意:以下内容适用于 bashkshzsh ,但不适用于(大多数)严格遵守POSIX的shell,例如{{1 }};因此,当你定位dash时,你必须双引用/bin/sh 的RHS。 [1]

  • 双引号是 可选,只有在您的RHS的 literal 部分(要分配的值)既不包含空格也不包含其他shell元字符时。
  • 引用的变量的值是否包含空格/元字符重要 - 请参阅下文。
    • 再次:当使用export时, sh有关,所以总是在那里加双引号。

在这种情况下你可以在没有双引号的情况下离开的原因是类似POSIX的shell中的 变量赋值语句以不同的方式解释它们的RHS em> arguments 传递给命令 ,如POSIX规范section 2.9.1中所述:

  • 具体来说,即使执行初始分词 ,它也仅适用于未扩展(原始)RHS(这就是 / LI>

  • 仅适用于形式
    正版赋值语句 所有类似POSIX的shell
    中的export,即,如果变量名称前面没有 no命令名称;请注意,这包括 prepended 分配给命令以为其定义ad-hoc环境变量,例如<name>=<value>

  • 在其他命令的上下文中分配应该始终是双引号,以确保安全:

    • 使用foo=$bar cmd ...(在(大部分)严格遵守POSIX的shell中,例如sh),dash的作业被视为常规命令export部分被视为foo=$bar内置的第一个参数,因此照常处理(受结果的分词影响< / em>,也是。) (POSIX没有指定涉及(显式)变量赋值的任何其他命令; exportdeclaretypeset是非标准扩展)。< / p>

    • localbashksh,与POSIX理解偏差,将分配逻辑扩展到zshexport foo=$bar。换句话说:typeset/declare/local foo=$bar中的bashkshzsh命令被视为分配,因此引用不是&#39严格必要

      • 也许令人惊讶的是export/typeset/declare/local,它也选择实现 -POSIX dash内置 [2] ,不会将赋值逻辑扩展到它;但是,它与local行为一致。
    • 传递给export的作业(例如env)也会作为命令参数进行扩展,因此需要双引号 - env foo=$bar cmd ...除外。

      • zsh envexport ksh的行为与bash的行为不同,因为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"

示例

此示例表明,在bashkshzsh中,即使使用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内置。

答案 1 :(得分:2)

test 123是UNIX上的有效路径名。尝试

PATH=test 123

它将返回:

123: command not found

甚至

export PATH=test 123

将返回

bash export: `123': not a valid identifier

它能回答你的问题吗?

老实说,我不会遵循这样的第四方风格指南。虽然我很惊讶,即使谷歌也会宣传这些错误的建议。

我会跟着:

(小心延伸)

答案 2 :(得分:2)

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

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

但是,除非将引号作为值的一部分,否则docker compose不需要将值包装在引号中,而是需要使用不带引号定义的环境变量。再次,如上面的网址所述

  

没有特别处理引号(即它们将是   VAL的一部分,你已被警告;)

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