n<<-word此处-文档分隔符 如果word的任何部分是引号,则分隔符是删除word引号的结果,此处文档中的行不会展开。如果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'发布于 2020-05-07 01:52:13
/bin/bash<
正如您可以从错误消息中推断出来的那样,本文档将被扩展为:
/bin/bash<<EOF
#!/bin/bash
echo 5.0.17(1)-release
EOF听起来就像你所期望的:它正在被扩展到外壳的版本。问题不在于此文档或扩展;问题在于未引用的括号是语法错误。尝试手动运行echo命令,您将得到相同的错误:
$ echo 5.0.17(1)-release
bash: syntax error near unexpected token `('要解决这个问题,您可以添加额外的引号:
/bin/bash<<EOF
echo '$BASH_VERSION'
EOF这将工作和打印外壳的版本。我使用单引号来证明这些引号不会抑制变量的扩展。外壳没有看到这些引号。只有内壳才能做到。
(我也摆脱了#!/bin/bash的“谢邦线”。没有必要这样做,因为您正在显式调用bash。)
然而,的报价并不是100%的健壮。,如果$BASH_VERSION碰巧包含单引号,那么您就有问题了。引号使括号( )安全,但它们不是万无一失的。作为一个一般的技术,如果你想让这是完全安全的,无论什么特殊的角色在游戏中,你将不得不跳过一些丑陋的箍。
printf '%q'转义所有特殊字符。
/bin/bash <这将扩展到echo 5.0.17\(1\)-release。<<'EOF'禁用脚本中的内插。
OUTER_VERSION="$BASH_VERSION“/bin/bash <<' EOF‘回声"$OUTER_VERSION”EOF
这将是我的选择。我更喜欢尽可能地使用<<'EOF'表单。让父shell内插要传递给子shell的脚本可能会让人感到困惑和难以解释。此外,显式的$OUTER_VERSION变量使它非常清楚正在发生什么。bash -c 'script'而不是heredoc,然后将版本作为命令行参数传递进来。
bash -c‘回声“$1’bash‘$BASH_VERSION’
我可能会用这个作为单行脚本。发布于 2020-05-07 01:51:17
如果不引用EOF,则在将原始shell作为输入传递给被调用的shell之前,将原始shell中的变量展开。所以这相当于执行
echo 3.2.57(1)-release在调用的shell中。这是无效的bash语法,因此您将得到一个错误。
引用这个词可以阻止变量展开,因此调用的shell接收$BASH_VERSION,并扩展它本身。
发布于 2020-05-07 01:53:06
在第一种情况下,引号阻止了这里文档中的任何更改,因此子shell可以看到echo $BASH_VERSION,并展开字符串并回显它。
在第二种情况下,缺少引号意味着第一个shell扩展信息并看到echo 3.2.57(1)-release,如果在命令行输入该引用,则会得到语法错误。
如果在这两种情况下都使用echo "$BASH_VERSION",那么两者都可以工作,但是不同的shell会扩展$BASH_VERSION。
https://stackoverflow.com/questions/61648422
复制相似问题