如果我单引号EOF,它可以工作。我认为是因为要调用的bash[n]<<[-]word here-document delimiter
如果单词的任何部分为quoted,则定界符是单词上引号删除的结果,并且本文档中的行不会扩展。如果未引用word,则对本文的所有行进行参数扩展,命令替换和算术扩展,字符序列\ newline将被忽略,并且必须使用'\'来引用字符'\','$ '和'`'。
/ 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'
/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
碰巧包含单引号,则可能会出现问题。引号使括号(
)
安全,但并非万无一失。作为一种通用技术,如果希望此方法完全安全无论正在播放什么特殊字符
- 使用
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"
我可能会将此用于单行脚本。
EOF
,则将原始文档外壳扩展heredoc中的变量,然后将其作为输入传递给调用的外壳。因此,它等效于执行echo 3.2.57(1)-release
在被调用的shell中。bash
语法无效,因此会出现错误。引用该词可防止变量扩展,因此被调用的shell将从字面上接收
$BASH_VERSION
,并对其自身进行扩展。
echo $BASH_VERSION
,它会扩展字符串并回显它。[在第二种情况下,没有引号意味着第一个外壳扩展了信息并且看到了echo 3.2.57(1)-release
,如果在命令行中键入它,则会出现语法错误。
如果您在两者中都使用echo "$BASH_VERSION"
,则两者都可以使用,但是不同的外壳将扩展$BASH_VERSION
。