Bash语法错误:意外的文件结尾

153

对不起,这是一个非常简单的 Bash 脚本。以下是代码:

#!/bin/bash
# june 2011

if [ $# -lt 3 -o $# -gt 3 ]; then
   echo "Error... Usage: $0 host database username"
   exit 0
fi

运行sh file.sh后:

语法错误:意外的文件结尾

23个回答

185
我认为file.sh是使用CRLF行终止符的。 运行。
dos2unix file.sh

那么问题将被解决。

你可以在Ubuntu中使用以下命令安装dos2unix:

sudo apt-get install dos2unix

这个问题的原因是什么?我通常在Windows上工作,但需要将脚本转移到Unix系统。 - CMCDragonkai
1
Windows中的换行符为"\r\n",而Linux中为"\n"。 - clyfish
10
@KeesdeKooter 我不会因为某件事对你没用就给它投反对票,显然它对其他28个人有用。简单地说“对我没用”就可以了。这就是为什么SO允许在一个问题中有多个答案,因为问题可能有多种解决方案。 - Jeff Wilbert
3
对于我来说,Notepad++编辑器的“编辑”>“EOL转换”>“旧Mac格式”解决了这个问题。 - raktale
1
安装之前,可以尝试在vim中执行命令':set fileformat=unix'。这对我在Windows子系统Linux(WSL)中运行时有效。 - Jay Killeen
显示剩余2条评论

181

还有一件需要检查的事情(突然想到):

  • 在单行函数的末尾加上分号

也就是说,这个看似无害的片段会导致相同的错误:

die () { test -n "$@" && echo "$@"; exit 1 }
为了让这个不灵敏的解析器满意:
die () { test -n "$@" && echo "$@"; exit 1; }

7
+1 也适用于带有方括号的代码片段,比如:[[ "$#" == 1 ]] && [[ "$arg" == [1,2,3,4] ]] && printf "%s\n" "blah" || { printf "%s\n" "blahblah"; usage; } ............ 注意花括号内部分号的位置,在之前调用已定义的函数'usage'后。如果忘记了这一点,将会得到相同的语法错误:意外的eof。 - Cbhihe
1
你做得很好。实际上,最简单的事情就是加上 ;。每个语句都需要以 ; 结尾,所以在末尾加上它,例如:如果 [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fi 将产生错误,而 if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash; fi; 则不会出错……注意一下小小的分号,即在 .bashfi 后面。 - Emmanuel Mahuni
2
我从一个 zsh 用户分享的脚本中得到了这个。前者在 zsh 中可以工作,但在 shbash 中无法工作。真希望我是四个人,这样我就可以给它四个赞了。 - Davos

74

我刚刚因在一个 if 从句中使用错误的语法而遇到了这个错误消息。

  • else if(语法错误:意外的文件结尾)
  • elif(正确的语法)

我通过注释一些代码来进行调试,直到它能够正常工作。


3
非常感谢你!请有人给这个人颁发一枚奖章。 - Happiehappie

37

一个未关闭的if => fi子句也会引发此错误。

提示:如果你的脚本非常庞大,可以使用trap进行调试...

例如:

set -x
trap read debug

2
我完全忘记了“fi”!谢谢 :) 如果可以的话,请详细说明一下您使用trap的提示,以使每个人都受益。 - Neithan Max
4
抱歉让你等了这么久,我的朋友。"trap" 命令是一种调试脚本的方式,基本上可以在每一行之后中断执行。更多讨论请看这里:https://dev59.com/m2ox5IYBdhLWcg3wnlpI - theRiley
2
非常有用,非常感谢。请注意,一旦遇到 fi,就会出现“意外文件结尾”错误。 - Stephane B.
啊,所以,应该不把那些设置和陷阱命令写进实际的脚本中,就像你建议的那篇文章中所说的那样,这样可以澄清你的答案?你应该在shell中编写它,然后调用脚本。请澄清一下,这样可以避免大家绕圈子。 - markling
@Markling - 我预计人们会在调试脚本后将陷阱移除。 - theRiley
也就是说,如果他们得到足够好的建议,知道什么是陷阱,以及应该在哪里和如何设置它! - markling

17

我从StackOverflow上类似的问题中找到了这个答案

在Vim中打开文件并尝试

:set fileformat=unix

将行结尾符转换为Unix格式,看看是否解决了问题。如果在Vim中编辑,请输入命令:set fileformat=unix并保存文件。其他一些编辑器也可以转换行结尾符,例如Notepad++或Atom

感谢@lemongrassnginger


这些只是替代方法,如被接受的答案所建议的那样,用于执行dos2unix - ulidtko

12

当我将"if-fi"语句写在一行时,遇到了问题:

if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fi

使用多行解决了我的问题:

if [ -f ~/.git-completion.bash ]; then 
    . ~/.git-completion.bash
 fi

2
你也可以像这样保持一行:if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash; fi(注意末尾附近的;)。 - YorSubs

12

当我尝试使用括号调用函数时,就会发生这种情况,例如:

run() {
  echo hello
}

run()

应该是:

run() {
  echo hello
}

run

2
谢谢!这正是我的问题,我以为它与其他答案有关。 - MrEduar

8

我发现了这篇帖子,但里面的答案并没有帮助到我,不过最终我还是找到了问题出在哪里。我有一个

cat > temp.txt < EOF
some content
EOF

问题在于我把上面的代码复制到一个函数中,无意间缩进了代码。需要确保最后的EOF没有被缩进。

2
这正是我的情况。我将 EOF 缩进了四个空格,因此 bash 没有解析它。移除空格后问题得到解决。 - ᴍᴇʜᴏᴠ

7
在Cygwin上,我需要执行以下操作:-
 export SHELLOPTS
 set -o igncr

在 .bash_profile 中添加这个命令,这样我就不需要运行 unix2dos 命令了。


5

针对Windows操作系统:

在我的情况下,我正在使用Windows操作系统,在运行autoconf时遇到了相同的错误。

  • 我只需用 NOTEPAD++ IDE打开configure.ac文件。
  • 然后,我将文件转换为 Windows (CR LF) 格式,并进行了EOL转换。具体方法如下:

    编辑 -> EOL转换 -> Windows (CR LF)


谢谢,这对我很有帮助。我使用OpenShift s2i nginx。 - Andreas Panagiotidis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接