Bash-<< [

问题描述 投票:1回答:3
GNU Bash - 3.6.6 Here Documents

[n]<<[-]word here-document delimiter
如果单词的任何部分为

quoted,则定界符是单词上引号删除的结果,并且本文档中的行不会扩展。如果未引用word,则对本文的所有行进行参数扩展,命令替换和算术扩展,字符序列\ newline将被忽略,并且必须使用'\'来引用字符'\','$ '和'`'。

如果我单引号EOF,它可以工作。我认为是因为要调用的bash

/ bin / bash

进程获取未扩展的字符串,然后被调用的进程解释了这些行。$ /bin/bash<<'EOF' #!/bin/bash echo $BASH_VERSION EOF 3.2.57(1)-release
但是,以下导致错误。我以为BASH_VERSION会被扩展,当前bash进程的版本将传递给

/ bin / bash

进程以进行调用。但不起作用。$ /bin/bash<<EOF #!/bin/bash echo $BASH_VERSION EOF /bin/bash: line 2: syntax error near unexpected token `(' /bin/bash: line 2: `echo 5.0.17(1)-release'
bash heredoc
3个回答
4
投票
/bin/bash<<EOF #!/bin/bash echo $BASH_VERSION EOF
您可以从错误消息中推断出,heredoc被扩展为:

/bin/bash<<EOF #!/bin/bash echo 5.0.17(1)-release EOF

听起来这就是您所期望的:它正在扩展到外壳的版本。问题与heredoc或扩展无关;这是因为没有引号的括号是语法错误。尝试仅手动运行echo命令,您将得到相同的错误:

$ echo 5.0.17(1)-release bash: syntax error near unexpected token `('

要解决此问题,您可以添加额外的引号:

/bin/bash<<EOF echo '$BASH_VERSION' EOF

这将起作用并打印外壳的版本。我使用单引号来表明这些引号将

not禁止变量扩展。外壳看不到这些引号。只有内壳可以。

((我也摆脱了#!/bin/bash shebang行。由于您显式调用bash,因此不需要它。)

但是,报价并非100%可靠。如果$BASH_VERSION碰巧包含单引号,则可能会出现问题。引号使括号( )安全,但并非万无一失。作为一种通用技术,如果希望此方法完全安全无论正在播放什么特殊字符

,您都必须跳过一些丑陋的箍。
  1. 使用printf '%q'转义所有特殊字符。

    /bin/bash <<EOF echo $(printf '%q' "$BASH_VERSION") EOF

这将扩展为echo 5.0.17\(1\)-release

  • 将其作为环境变量传递,并使用<<'EOF'禁用脚本中的插值。

    OUTER_VERSION="$BASH_VERSION" /bin/bash <<'EOF' echo "$OUTER_VERSION" EOF

    这是我的选择。我希望尽可能使用<<'EOF'表格。由父外壳插入要传递给子外壳的脚本可能会造成混淆,并且难以推理。此外,显式的$OUTER_VERSION变量使您可以清楚地了解正在发生的事情。
  • 使用bash -c 'script'代替Heredoc,然后将版本作为命令行参数传递。

    bash -c 'echo "$1"' bash "$BASH_VERSION"

    我可能会将此用于单行脚本。

  • 0
    投票
    如果不引用EOF,则将原始文档外壳扩展heredoc中的变量,然后将其作为输入传递给调用的外壳。因此,它等效于执行

    echo 3.2.57(1)-release

    在被调用的shell中。 bash语法无效,因此会出现错误。

    引用该词可防止变量扩展,因此被调用的shell将从字面上接收$BASH_VERSION,并对其自身进行扩展。


    0
    投票
    在第一种情况下,引号阻止了here文档中的任何更改,因此子shell看到echo $BASH_VERSION,它会扩展字符串并回显它。

    [在第二种情况下,没有引号意味着第一个外壳扩展了信息并且看到了echo 3.2.57(1)-release,如果在命令行中键入它,则会出现语法错误。

    如果您在两者中都使用echo "$BASH_VERSION",则两者都可以使用,但是不同的外壳将扩展$BASH_VERSION

    © www.soinside.com 2019 - 2024. All rights reserved.