shell 中的 <<EOF 和 <<\EOF heredocs 有什么区别
What's the difference between <<EOF and <<\EOF heredocs in shell
我注意到它们之间的几个区别:
在 <<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
将打印空行。
那么它们之间有什么区别,合法的记录行为是什么?
阅读 Advanced Bash Scripting Guide & bash reference manual in particular about redirections:
The format of here-documents is:
<<[-]word
here-document
delimiter
No parameter and variable expansion, command substitution, arithmetic
expansion, or filename expansion is performed on word. If any
characters in word are quoted, the delimiter is the result of quote
removal on word, and the lines in the here-document are not expanded.
If word is unquoted, all lines of the here-document are subjected to
parameter expansion, command substitution, and arithmetic expansion,
the character sequence \newline is ignored, and ‘\’ must be used to
quote the characters ‘\’, ‘$’, and ‘`’.
文档:http://www.gnu.org/software/bash/manual/bash.html#Here-Documents
在您的第一个示例中,定界符未被引号括起来,因此会发生变量扩展,就好像您是 运行 代码
echo "s=fds
echo $s" | bash
在当前 shell 中扩展 $s
,其中它是空的。所以新的 shell 看到
s=fds
echo
来自POSIX spec:
If any character in word is quoted, the delimiter shall be formed by performing quote removal on word, and the here-document lines shall not be expanded. Otherwise, the delimiter shall be the word itself.
所以 <<EOF
版本有 shell 扩展所有变量 在 运行 这里的文档内容和 <<\EOF
(或 <<'EOF'
或 <<EO'F'
等)版本不扩展内容(在这种情况下让 bash
完成这项工作)。
尝试使用 cat
而不是 bash
来更清楚地了解正在发生的事情。
还有 printf '[%s]\n' "$s"
and/or 可能 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]
我注意到它们之间的几个区别:
在 <<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
将打印空行。
那么它们之间有什么区别,合法的记录行为是什么?
阅读 Advanced Bash Scripting Guide & bash reference manual in particular about redirections:
The format of here-documents is:
<<[-]word
here-document
delimiter
No parameter and variable expansion, command substitution, arithmetic expansion, or filename expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, the character sequence \newline is ignored, and ‘\’ must be used to quote the characters ‘\’, ‘$’, and ‘`’.
文档:http://www.gnu.org/software/bash/manual/bash.html#Here-Documents
在您的第一个示例中,定界符未被引号括起来,因此会发生变量扩展,就好像您是 运行 代码
echo "s=fds
echo $s" | bash
在当前 shell 中扩展 $s
,其中它是空的。所以新的 shell 看到
s=fds
echo
来自POSIX spec:
If any character in word is quoted, the delimiter shall be formed by performing quote removal on word, and the here-document lines shall not be expanded. Otherwise, the delimiter shall be the word itself.
所以 <<EOF
版本有 shell 扩展所有变量 在 运行 这里的文档内容和 <<\EOF
(或 <<'EOF'
或 <<EO'F'
等)版本不扩展内容(在这种情况下让 bash
完成这项工作)。
尝试使用 cat
而不是 bash
来更清楚地了解正在发生的事情。
还有 printf '[%s]\n' "$s"
and/or 可能 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]