我需要我的脚本从终端发送电子邮件。根据我在这里和网上许多其他地方看到的内容,我将其格式化如下:
/var/mail -s "$SUBJECT" "$EMAIL" << EOF
Here's a line of my message!
And here's another line!
Last line of the message here!
EOF
但是,当我运行此命令时,我收到此警告:
myfile.sh: line x: warning: here-document at line y delimited by end-of-file (wanted 'EOF')
myfile.sh: line x+1: syntax error: unexpected end of file
...其中第 x 行是程序中最后写入的代码行,第 y 行是其中包含
/var/mail
的行。我尝试用其他东西(EOF
、ENDOFMESSAGE
等)替换FINISH
,但无济于事。我在网上找到的几乎所有内容都是这样完成的,而且我对 bash 真的很陌生,所以我很难自己弄清楚它。有人可以提供帮助吗?
EOF
标记必须位于行的开头,您不能将其与它所附带的代码块一起缩进。
如果您写
<<-EOF
,您可以缩进,但必须使用 Tab 字符缩进,而不是空格。所以即使有了代码块,它仍然可能不会结束。
还要确保该行的 EOF
标记
之后没有空格。
开始或结束此处文档的行可能有一些不可打印或空白字符(例如回车符),这意味着第二个“EOF”与第一个“EOF”不匹配,并且不会结束此处文档就像它应该的那样。这是一个非常常见的错误,仅使用文本编辑器很难检测到。您可以使不可打印的字符可见,例如使用
cat
:
cat -A myfile.sh
一旦看到
cat -A
的输出,解决方案就会显而易见:删除有问题的字符。
请尝试删除前面的空格
EOF
:-
/var/mail -s "$SUBJECT" "$EMAIL" <<-EOF
使用
<tab>
代替 <spaces>
进行识别并使用 <<-EOF works fine.
"-"
删除了<tabs>
,而不是<spaces>
,但至少这有效。
对于任何在这里绊倒的人谷歌搜索“bash警告:此处文档由文件结尾分隔”,您可能会得到
警告:此处文档第 74 行由文件结尾分隔
...键入警告,因为 当您打算使用 here string 符号 (
<<
) 时,您不小心使用了 here document 符号 (<<<
)。 这就是我的情况。
注意,如果您这样做,也可能会出现此错误;
while read line; do
echo $line
done << somefile
因为在这种情况下
<< somefile
应阅读 < somefile
。
可能很旧,但在结尾 EOF 后有一个空格 << EOF blah blah EOF <-- this was the issue. Had it for years, finally looked it up here
当我想为 bash 函数使用 docstrings 时,我使用类似于此问题的 duplicate 中的 user12205 建议的解决方案。
了解我如何定义解决方案的 USAGE:
function foo {
# Docstring
read -r -d '' USAGE <<' END'
# This method prints foo to the terminal.
#
# Enter `foo -h` to see the docstring.
# It has indentations and multiple lines.
#
# Change the delimiter if you need hashtag for some reason.
# This can include $$ and = and eval, but won't be evaluated
END
if [ "$1" = "-h" ]
then
echo "$USAGE" | cut -d "#" -f 2 | cut -c 2-
return
fi
echo "foo"
}
所以
foo -h
产量:
This method prints foo to the terminal.
Enter `foo -h` to see the docstring.
It has indentations and multiple lines.
Change the delimiter if you need hashtag for some reason.
This can include $$ and = and eval, but won't be evaluated
解释
cut -d "#" -f 2
:检索 #
分隔行的第二部分。 (想象一个以“#”作为分隔符的 csv,第一列为空)。
cut -c 2-
:检索结果字符串的第二个到结束字符
另请注意,如果没有第一个参数,则
if [ "$1" = "-h" ]
的计算结果为 False
,不会出现错误,因为它会变成空字符串。
除了 Barmar 和 Joni 提到的其他答案之外,我注意到在使用
<<-EOF
时有时必须在 EOF 前后留下空行。
这是一种灵活的方法来处理多个缩进行,无需使用heredoc。
echo 'Hello!'
sed -e 's:^\s*::' < <(echo '
Some indented text here.
Some indented text here.
')
if [[ true ]]; then
sed -e 's:^\s\{4,4\}::' < <(echo '
Some indented text here.
Some extra indented text here.
Some indented text here.
')
fi
有关此解决方案的一些注释:
\
转义它们或用双引号替换字符串分隔符。在后一种情况下,请注意像
$(command)
这样的结构将被解释。如果字符串同时包含单引号和双引号,则必须至少进行某种转义。