此处文档给出'unexpected end of file'错误



我需要我的脚本从终端发送电子邮件。根据我在这里和网上许多其他地方看到的内容,我将其格式化为:

/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 标记必须位于行首,您不能将其与它附带的代码块一起缩进。

如果写<<-EOF可以缩进,但必须用制表符而不是空格缩进。因此,即使使用代码块,它仍然可能不会结束。

还要确保行上的EOF标记没有空格。

开始或结束 here-doc 的行可能有一些不可打印或空格字符(例如,回车符),这意味着第二个"EOF"与第一个不匹配,并且不会像它应该的那样结束 here-doc。这是一个非常常见的错误,仅使用文本编辑器很难检测到。您可以使不可打印的字符可见,例如使用 cat

cat -A myfile.sh

一旦你看到cat -A的输出,解决方案将是显而易见的:删除有问题的字符。

请尝试删除前面的空格EOF:-

/var/mail -s "$SUBJECT" "$EMAIL" <<-EOF

使用 <tab> 而不是 <spaces> 进行识别和使用 <<-EOF 可以正常工作。

"-"删除了<tabs>,而不是<spaces>,但至少这是有效的。

请注意,

如果这样做,也可能会出现此错误;

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

因为在这种情况下<< somefile应该读< somefile

对于任何在这里磕磕绊绊的人,如果用谷歌搜索"bash警告:这里文档由文件结尾分隔",可能是你得到了

警告:此处文档第 74 行由文件结尾分隔

。键入警告,因为当您打算使用此处字符串符号 ( <<< ) 时,您不小心使用了此处文档符号 ( << )。这就是我的情况。

可能

很旧,但我在结束 EOF 后有一个空格 <<EOF的等等等等EOF<--这就是问题所在。 好好多年了,终于查到这里了

当我想为我的 bash 函数提供文档字符串时,我在此问题的副本中使用类似于 user12205 建议的解决方案。

了解我如何为以下解决方案定义 USAGE:

  • 在我选择的 IDE 中自动格式化对我来说很好(崇高)
  • 是多行的
  • 可以使用空格或制表符作为缩进
  • 保留注释中的缩进。
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-:检索结果字符串的第二个到尾字符

另请注意,如果没有第一个参数(w/o error),if [ "$1" = "-h" ]的计算结果为 False,因为它变为空字符串。

这是一种灵活的方法,可以在不使用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。

除了 Barmar 和 Joni 提到的其他答案外,我还注意到在使用 <<-EOF 时,我有时必须在 EOF 之前和之后留下一个空白行。

相关内容

  • 没有找到相关文章

最新更新