Run Code Online (Sandbox Code Playgroud)[n]<<[-]word here-document delimiter如果 word 的任何部分被引用,则分隔符是对 word 引用删除的结果,并且 here-document 中的行不会被扩展。如果word不加引号,则here-document的所有行都进行参数扩展、命令替换和算术扩展,字符序列\newline被忽略,并且必须使用'\'来引用字符'\'、'$ ' 和 '`'。
如果我单引号 EOF,它的工作原理。我认为是因为要调用的bash /bin/bash进程获取未扩展的字符串,然后被调用的进程解释这些行。
$ /bin/bash<<'EOF'
#!/bin/bash
echo $BASH_VERSION
EOF
3.2.57(1)-release
Run Code Online (Sandbox Code Playgroud)
但是,以下内容导致错误。我认为 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'
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)/bin/bash<<EOF #!/bin/bash echo $BASH_VERSION EOF
正如您可以从错误消息中推断出的,heredoc 正在扩展为:
/bin/bash<<EOF
#!/bin/bash
echo 5.0.17(1)-release
EOF
Run Code Online (Sandbox Code Playgroud)
听起来这就是您所期望的:它正在扩展到外壳的版本。问题不在于heredoc 或扩展;未加引号的括号是语法错误。尝试只echo手动运行命令,你会得到同样的错误:
$ echo 5.0.17(1)-release
bash: syntax error near unexpected token `('
Run Code Online (Sandbox Code Playgroud)
要解决此问题,您可以添加额外的引号:
/bin/bash<<EOF
echo '$BASH_VERSION'
EOF
Run Code Online (Sandbox Code Playgroud)
这将起作用并打印外壳的版本。我使用单引号来证明这些引号不会抑制变量扩展。外壳看不到这些引号。只有内壳可以。
(我也去掉了#!/bin/bashshebang 行。没有必要,因为你明确调用了 bash。)
但是,引用并非 100% 可靠。如果$BASH_VERSION碰巧包含单引号,您就会遇到问题。引号使括号( )安全,但它们并非万无一失。作为一种通用技术,如果您希望无论出现什么特殊角色都完全安全,则必须跳过一些丑陋的圈套。
使用printf '%q'转义所有特殊字符。
/bin/bash <<EOF
echo $(printf '%q' "$BASH_VERSION")
EOF
Run Code Online (Sandbox Code Playgroud)
这将扩展到echo 5.0.17\(1\)-release.
将其作为环境变量传入并用于<<'EOF'禁用脚本内的插值。
OUTER_VERSION="$BASH_VERSION" /bin/bash <<'EOF'
echo "$OUTER_VERSION"
EOF
Run Code Online (Sandbox Code Playgroud)
这将是我的选择。我更喜欢<<'EOF'尽可能使用表格。让父 shell 插入传递给子 shell 的脚本可能会令人困惑且难以推理。此外,显式$OUTER_VERSION变量使发生的事情一目了然。
使用bash -c 'script'而不是heredoc,然后将版本作为命令行参数传入。
bash -c 'echo "$1"' bash "$BASH_VERSION"
Run Code Online (Sandbox Code Playgroud)
我可能会用它来编写单行脚本。
| 归档时间: |
|
| 查看次数: |
448 次 |
| 最近记录: |