here-document 给出“文件意外结束”错误
Posted
技术标签:
【中文标题】here-document 给出“文件意外结束”错误【英文标题】:here-document gives 'unexpected end of file' error 【发布时间】:2013-09-10 17:34:38 【问题描述】:我需要我的脚本从终端发送电子邮件。根据我在这里和网上许多其他地方看到的内容,我将其格式化为:
/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
的行。我尝试用其他东西(ENDOFMESSAGE
、FINISH
等)替换 EOF
,但无济于事。我在网上找到的几乎所有东西都是这样完成的,而且我对 bash 真的很陌生,所以我很难自己弄清楚。有人可以提供任何帮助吗?
【问题讨论】:
EOF
行是否缩进?它必须在行首。
确实如此,但仅限于整个语句的嵌套。所以它必须一直向左?
另外,确保没有尾随字符(包括回车!)
如果你缩进只有个制表符,你可以使用<<-EOF
-- gnu.org/software/bash/manual/bashref.html#Here-Documents
【参考方案1】:
EOF
标记必须在行首,你不能将它与它的代码块一起缩进。
如果你写<<-EOF
,你可以缩进它,但它必须缩进 Tab 字符,而不是空格。所以即使有代码块,它仍然可能不会结束。
还要确保在行上的EOF
标记之后没有空格。
【讨论】:
在上面的代码示例中,EOF 标记位于行首。 我在编辑历史中没有看到它,但它最初一定是缩进的,因为我不是唯一一个指出这个问题的人。 即使我删除了所有不必要的空格,我也会收到此错误。 检查CR字符,并使用dos2unix
修复它。【参考方案2】:
开始或结束 here-doc 的行可能有一些不可打印或空白字符(例如,回车),这意味着第二个“EOF”与第一个不匹配,并且不会结束 here -doc 应该如此。这是一个非常常见的错误,仅使用文本编辑器很难检测到。您可以使用 cat
使不可打印的字符可见:
cat -A myfile.sh
一旦您看到来自 cat -A
的输出,解决方案就会很明显:删除有问题的字符。
【讨论】:
【参考方案3】:请尝试删除EOF
:-之前的空格-
/var/mail -s "$SUBJECT" "$EMAIL" <<-EOF
使用<tab>
而不是<spaces>
进行标识并且使用
"-"
删除了 <tabs>
,而不是 <spaces>
,但至少这是可行的。
【讨论】:
第一个建议没有帮助(您是否测试过空间是否会导致问题?)。第二个只有在 EOF 行使用 TAB 缩进时才有帮助,而不是空格。 我认为终止标记不能有前导空格【参考方案4】:注意,如果你这样做,也会得到这个错误;
while read line; do
echo $line
done << somefile
因为在这种情况下<< somefile
应该是< somefile
。
【讨论】:
【参考方案5】:这是一种处理多个缩进行不使用使用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)
这样的构造将被解释。如果字符串同时包含单引号和双引号,则您至少必须转义。
给定的示例打印一个尾随的空行,有很多方法可以摆脱它,这里不包括在内,以尽量减少提案的混乱
灵活性来自于您可以轻松控制应该保留或离开多少前导空间,前提是您当然知道一些 sed REGEXP。
【讨论】:
【参考方案6】:当我想为我的 bash 函数使用 docstrings 时,我使用类似于 user12205 在此问题的 duplicate 中的建议的解决方案。
查看我如何为解决方案定义 USAGE:
在我选择的 IDE 中自动格式化非常适合我 (sublime) 是多行的 可以使用空格或制表符作为缩进 在评论中保留缩进。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
,没有错误,因为它变成了一个空字符串。
【讨论】:
【参考方案7】:确保将结尾 EOF 放在新行的开头
【讨论】:
【参考方案8】:除了 Barmar 和 Joni 提到的其他答案外,我注意到在使用 <<-EOF
时,有时我必须在 EOF 前后留一个空行。
【讨论】:
无论是理论还是实践,我都找不到对此的支持。投反对票是迷信。 我有一个用括号包裹的多行 here-doc 以重定向到cat
并且由于格式的原因,在我关闭 here-doc 标记之前,我需要在结束括号之前添加一个输入,否则我会得到这种不匹配。投票对“某些”人来说是完全有效的,尽管这可能不太可能发生。
我讨厌为迷信做出贡献,但我也遇到了这个问题,并在我的 EOF 结束后添加了一个空行。 (在 docker 中运行的 ubuntu 19.10;这是在 bootstrap.sh 脚本中)。空白行修正了这个错误。以上是关于here-document 给出“文件意外结束”错误的主要内容,如果未能解决你的问题,请参考以下文章
xsd:包含soapUI中的异常:org.apache.xmlbeans.XmlException:org.apache.xmlbeans.XmlException:错误:null之后的文件意外结束(
R 是啥时候开始支持类似 here-document 的功能的? [关闭]
nginx 文件意外结束,期待“;”或 /etc/nginx/sites-enabled/default:20 中的 "" 在 Raspbian 上