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 的行。我尝试用其他东西(ENDOFMESSAGEFINISH 等)替换 EOF,但无济于事。我在网上找到的几乎所有东西都是这样完成的,而且我对 bash 真的很陌生,所以我很难自己弄清楚。有人可以提供任何帮助吗?

【问题讨论】:

EOF 行是否缩进?它必须在行首。 确实如此,但仅限于整个语句的嵌套。所以它必须一直向左? 另外,确保没有尾随字符(包括回车!) 如果你缩进只有个制表符,你可以使用&lt;&lt;-EOF -- gnu.org/software/bash/manual/bashref.html#Here-Documents 【参考方案1】:

EOF 标记必须在行首,你不能将它与它的代码块一起缩进。

如果你写&lt;&lt;-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

使用&lt;tab&gt; 而不是&lt;spaces&gt; 进行标识并且使用

"-" 删除了 &lt;tabs&gt;,而不是 &lt;spaces&gt;,但至少这是可行的。

【讨论】:

第一个建议没有帮助(您是否测试过空间是否会导致问题?)。第二个只有在 EOF 行使用 TAB 缩进时才有帮助,而不是空格。 我认为终止标记不能有前导空格【参考方案4】:

注意,如果你这样做,也会得到这个错误;

while read line; do
  echo $line
done << somefile

因为在这种情况下&lt;&lt; somefile 应该是&lt; 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 提到的其他答案外,我注意到在使用 &lt;&lt;-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之后的文件意外结束(

解析错误:语法错误,文件意外结束,期待'`' [重复]

AWS Spectrum 扫描错误压缩文件意外结束

解析错误:语法错误,文件意外结束[重复]

R 是啥时候开始支持类似 here-document 的功能的? [关闭]

nginx 文件意外结束,期待“;”或 /etc/nginx/sites-enabled/default:20 中的 "" 在 Raspbian 上