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

标签 bash shell dotfiles

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

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

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

谷歌 shell style指南建议避免路径名的引号。相比之下,许多流行的点文件存储库(例如 Zach Holman 的 here)使用引号。在路径中使用引号是否有优势?

最佳答案

尖顶到@gniourf_gniourf@chepner为了他们的帮助。

tl;博士

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

如果要添加 ~ -based 路径,有选择地离开 ~/不加引号以确保~被扩展了;例如:export PATH=~/"bin:$PATH" .~规则见下变量赋值的扩展。
或者,只需使用 $HOME在单个双引号字符串中:export PATH="$HOME/bin:$PATH"
注意:以下内容适用于 bash , ksh , 和 zsh ,但不是(主要)严格符合 POSIX 的 shell,例如 dash ;因此,当您定位时 /bin/sh , 你必须双引号 export 的 RHS .[1]

  • 双引号是 可选,仅当 RHS 的文字部分(要分配的值)既不包含空格也不包含其他 shell 元字符时。
  • 引用的变量的值是否包含空格/元字符并不重要 - 见下文。
  • 再说一遍:这与 sh 很重要, 当 export被使用,所以总是在那里双引号。

  • 在这种情况下,您无需双引号即可逃脱的原因是 POSIX 类 shell 中的变量赋值语句对 RHS 的解释与传递给命令的参数不同 ,如 section 2.9.1 中所述POSIX 规范:
  • 具体来说,即使执行了初始分词,它也仅适用于未扩展的(原始)RHS(这就是为什么您确实需要在文字中使用空格/元字符进行引用),而不适用于其结果。
  • 仅适用于形式的真正赋值语句<name>=<value>在所有类似 POSIX 的 shell 中 ,即如果变量名前没有命令名;请注意,这包括添加到命令前的赋值,以便为其定义临时环境变量,例如,foo=$bar cmd ... .
  • 其他命令上下文中的赋值应始终用双引号引起来 ,为了安全:
  • sh (在(大部分)严格符合 POSIX 的 shell 中,例如 dash )与 export 的分配被视为常规命令,foo=$bar部分被视为 export 的第一个参数内置,因此照常处理(也受到结果的分词)。
    (POSIX 没有指定任何其他涉及(显式)变量赋值的命令; declaretypesetlocal 是非标准扩展)。
  • 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 的行为根本不同)。
  • 波浪号 ( ~ ) 扩展在真正的赋值语句中发生如下 :
  • 除了~需要不加引号,像往常一样,它也只适用于:
  • 如果整个 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 标准的 future 版本可能会引入 local内置。

    关于bash - 我应该在环境路径名中使用引号吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33318499/

    相关文章:

    java - java 中的 curl -k 等效项,用于抑制认证验证并通过用户名 :api key

    linux - 如何处理本地点文件存储库?

    shell - 如何在fish shell中导出函数

    bash - 如何在 bash 中测试一个字符串是否以另一个字符串开头?

    json - 如何从 shell 脚本向 JSON 文件添加新元素

    java - 如何使用bash或java将三个不同的sqlite3数据库D1、D2和D3附加到另一个数据库D4

    bash - #!bin/sh 在centOS 错误命令启动中调用程序

    linux - 从文本中查找重复项的位置

    linux - 正则表达式模式在 sublime text 中找到,但在 linux sed 命令 sed 中找不到