我注意到它们之间存在一些区别:
在<<EOF
heredoc中,无法将新值分配给变量:
bash <<EOF
s=fds
echo $s
EOF
将打印空行,其中
bash <<\EOF
s=fds
echo $s
EOF
将打印变量s
的值。
全局变量可以在<<EOF
内访问,但不能在<<\EOF
内访问(export
可以访问<<\EOF
内的变量):
s=fds
bash <<EOF
echo $s
EOF
将打印值fds
,其中,
s=fds
bash <<\EOF
echo $s
EOF
将打印空行。
那么它们之间的区别是什么是合法的记录行为?
答案 0 :(得分:8)
来自POSIX spec:
如果引用 word 中的任何字符,则应通过在字上执行引号删除来形成分隔符,并且不应展开here-document行。否则,分隔符应为单词本身。
因此<<EOF
版本的shell会在运行此处的doc内容和<<\EOF
(或<<'EOF'
或<<EO'F'
之前展开所有变量等)版本不扩展内容(在这种情况下允许bash
执行该操作)。
使用cat
代替bash
进行尝试,以便更清楚地了解正在发生的事情。
同时使用printf '[%s]\n' "$s"
和/或可能bash -x
代替bash
:
$ bash -x <<EOF
s=fds
printf '[%s]\n' "$s"
EOF
+ s=fds
+ printf '[%s]\n' ''
[]
$ bash -x <<\EOF
s=fds
printf '[%s]\n' "$s"
EOF
+ s=fds
+ printf '[%s]\n' fds
[fds]
答案 1 :(得分:1)
文档:http://www.gnu.org/software/bash/manual/bash.html#Here-Documents
在你的第一个例子中,分隔符是不加引号的,因此发生了变量扩展,就像你正在运行代码一样
echo "s=fds
echo $s" | bash
在当前shell中展开$s
,它是空的。所以新shell看到了
s=fds
echo
答案 2 :(得分:0)
阅读Advanced Bash Scripting Guide&amp; bash reference manual特别关于redirections:
here-documents的格式为:
<<[-]word
here-document
delimiter
无参数和变量扩展,命令替换,算术 对单词执行扩展或文件名扩展。如果有的话 引用的单词中的字符,分隔符是引用的结果 删除单词,并且不会展开here-document中的行。 如果单词不加引号,则here-文档的所有行都受到约束 参数扩展,命令替换和算术扩展, 字符序列\ newline被忽略,'\'必须用于 引用字符'\','$'和'`'。