简体   繁体   English

意外令牌“完成”附近的 BASH 语法错误

[英]BASH Syntax error near unexpected token 'done'

Any idea of what the problem could be?知道问题可能是什么吗?

My code is:我的代码是:

#!/bin/bash
while :
do
echo "Press [CTRL+C] to stop.."
sleep 1
done

Saved it as .sh and ran bash file.sh将其保存为 .sh 并运行 bash file.sh

CentOS 6 32-bit CentOS 6 32 位

What is the issue?问题是什么? First time EVER using BASH, need it for a simple infinite loop on something.第一次使用 BASH,需要它来做一个简单的无限循环。

Run cat -v file.sh .运行cat -v file.sh

You most likely have a carriage return or no-break space in your file.您的文件中很可能有回车或不间断空格。 cat -v will show them as ^M and M-BM- or M- respectively. cat -v将它们分别显示为^MM-BM-M- It will similarly show any other strange characters you might have gotten into your file.它同样会显示您可能已进入文件的任何其他奇怪字符。

Remove the Windows line breaks with删除 Windows 换行符

tr -d '\r' < file.sh > fixedfile.sh

I was getting the same error on Cygwin;我在 Cygwin 上遇到了同样的错误; I did the following (one of them fixed it):我做了以下事情(其中一个修复了它):

  1. Converted TABS to SPACESTABS转换为SPACES
  2. ran dos2unix on the .(ba)sh file.(ba)sh文件上运行dos2unix

What is the error you're getting?你得到什么错误?

$ bash file.sh
test.sh: line 8: syntax error: unexpected end of file

If you get that error, you may have bad line endings.如果您收到该错误,则可能有错误的行尾。 Unix uses <LF> at the end of the file while Windows uses <CR><LF> . Unix 在文件末尾使用<LF>而 Windows 使用<CR><LF> That <CR> character gets interpreted as a character.<CR>字符被解释为一个字符。

You can use od -a test.sh to see the invisible characters in the file.您可以使用od -a test.sh查看文件中的不可见字符。

$ od -a test.sh
0000000    #   !   /   b   i   n   /   b   a   s   h  cr  nl   #  sp  cr
0000020   nl   w   h   i   l   e  sp   :  cr  nl   d   o  cr  nl  sp  sp
0000040   sp  sp   e   c   h   o  sp   "   P   r   e   s   s  sp   [   C
0000060    T   R   L   +   C   ]  sp   t   o  sp   s   t   o   p   "  cr
0000100   nl  sp  sp  sp  sp   s   l   e   e   p  sp   1  cr  nl   d   o
0000120    n   e  cr  nl                                                
0000124

The sp stands for space, the ht stands for tab, the cr stands for <CR> and the nl stands for <LF> . sp代表空格, ht代表制表符, cr代表<CR>nl代表<LF> Note that all of the lines end with cr followed by a nl character.请注意,所有行都以cr结尾,后跟nl字符。

You can also use cat -v test.sh if your cat command takes the -v parameter.如果你的cat命令带有-v参数,你也可以使用cat -v test.sh

If you have dos2unix on your box, you can use that command to fix your file:如果您的机器上有dos2unix ,您可以使用该命令来修复您的文件:

$ dos2unix test.sh

Might help someone else : I encountered the same kind of issues while I had done some "copy-paste" from a side Microsoft Word document, where I took notes, to my shell script(s).可能对其他人有帮助:当我从我做笔记的 Microsoft Word 文档中“复制粘贴”到我的 shell 脚本时,我遇到了同样的问题。

Re-writing, manually, the exact same code in the script just solved this.手动重写脚本中完全相同的代码就解决了这个问题。

It was quite un-understandable at first, I think Word's hidden characters and/or formatting were the issue.一开始很难理解,我认为 Word 的隐藏字符和/或格式是问题所在。 Obvious but not see-able ... I lost about one hour on this (I'm no shell expert, as you might guess ...)明显但不可见......我为此损失了大约一个小时(我不是 shell 专家,你可能猜到了......)

There's a way you can get this problem without having mixed newline problems (at least, in my shell, which is GNU bash v4.3.30):有一种方法可以在没有混合换行问题的情况下解决这个问题(至少在我的 shell 中,即 GNU bash v4.3.30):

#!/bin/bash
# foo.sh

function foo() {
    echo "I am quoting a thing `$1' inside a function."
}

while [ "$input" != "y" ]; do
    read -p "Hit `y' to continue: " -n 1 input
    echo
done

foo "What could possibly go wrong?"
$ ./foo.sh
./foo.sh: line 11: syntax error near unexpected token `done'
./foo.sh: line 11: `done'

This is because bash expands backticks inside double-quoted strings (see the bash manual on quoting and command substitution ), and before finding a matching backtick, will interpret any additional double quotes as part of the command substitution:这是因为 bash 会在双引号字符串中扩展反引号(请参阅 bash 手册中的引用命令替换),并且在找到匹配的反引号之前,会将任何额外的双引号解释为命令替换的一部分:

$ echo "Command substitution happens inside double-quoted strings: `ls`"
Command substitution happens inside double-quoted strings: foo.sh
$ echo "..even with double quotes: `grep -E "^foo|wrong" foo.sh`"
..even with double quotes: foo "What could possibly go wrong?"

You can get around this by escaping the backticks in your string with a backslash, or by using a single-quoted string.您可以通过使用反斜杠转义字符串中的反引号或使用单引号字符串来解决此问题。

I'm not really sure why this only gives the one error message, but I think it has to do with the function definition:我不太确定为什么这只给出一个错误消息,但我认为它与函数定义有关:

#!/bin/bash
# a.sh

function a() {
    echo "Thing's `quoted'"
}
a
while true; do
    echo "Other `quote'"
done
#!/bin/bash
# b.sh

echo "Thing's `quoted'"
while true; do
    echo "Other `quote'"
done
$ ./a.sh
./a.sh: line 10: syntax error near unexpected token `done'
./a.sh: line 10: `done'
$ ./b.sh
./b.sh: command substitution: line 6: unexpected EOF while looking for matching `''
./b.sh: command substitution: line 9: syntax error: unexpected end of file
Thing's quote'
./b.sh: line 7: syntax error near unexpected token `done'
./b.sh: line 7: `done'

Sometimes this error happens because of unexpected CR characters in file, usually because the file was generated on a Windows system which uses CR line endings.有时由于文件中出现意外的 CR 字符而发生此错误,通常是因为该文件是在使用 CR 行结尾的 Windows 系统上生成的。 You can fix this by running os2unix or tr , for example:您可以通过运行os2unixtr来解决此问题,例如:

tr -d '\015' < yourscript.sh > newscript.sh tr -d '\015' <yourscript.sh > newscript.sh

This removes any CR characters from the file.这将从文件中删除任何 CR 字符。

Open new file named foobar打开名为foobar的新文件

nano -w foobar

Input script输入脚本

 #!/bin/bash
 while [ 0 = 0 ]; do
   echo "Press [CTRL+C] to stop.."
   sleep 1
 done;

Exit and save退出并保存

CTRL + X then Y and Enter CTRL + X然后YEnter

Set script executable and run设置脚本可执行文件并运行

chmod +x foobar
./foobar

Had similar problems just now and these are two separate instances and solutions that worked for me:刚才有类似的问题,这些是对我有用的两个独立的实例和解决方案:

Case 1. Basically, had a space after the last command within my newline-separated for-loop, eg.案例1。基本上,在我的换行符分隔的for循环中的最后一个命令之后有一个空格,例如。 (imagining that | here represents the carat in a text editor showing where you are writing), this is what I saw when clicking around the end of the line of the last command in the loop: (想象一下|这里代表文本编辑器中的克拉,显示您正在编写的位置),这是我在循环中最后一个命令的行尾单击时看到的:

for f in $pathToFiles
do
   $stuff |
done

Notice the space before before the carat (so far as I know, this is something cat has no option do display visually (one way you could test is with something like od -bc yourscript.sh )).注意克拉之前的空格(据我所知,这是cat无法在视觉上显示的东西(您可以测试的一种方法是使用od -bc yourscript.sh类的东西))。 Changing the code to将代码更改为

for f in $pathToFiles
do
   $stuff| <--- notice the carat shows no ending space before the newline
done

fixed the problem.解决了这个问题。

Case 2. Was using a pseudo try-catch block for the for-loop (see https://stackoverflow.com/a/22010339/8236733 ) like案例 2.为 for 循环使用伪 try-catch 块(请参阅https://stackoverflow.com/a/22010339/8236733 ),例如

{
for f in $pathToFiles
do
   { $stuff } || { echo "Failed to complete stuff"; exit 255; }
done
} || { echo "Failed to complete loop"; exit 255; }

and apparently bash did not like the nested {} s.显然 bash 不喜欢嵌套的{} Changing to更改为

{
for f in $pathToFiles
do
   $stuff
done
} || { echo "Failed to complete loop"; exit 255; }

fixed the problem in this case.在这种情况下解决了问题。 If anyone can further explain either of these cases, please let me know more about them in the comments.如果有人可以进一步解释其中任何一种情况,请在评论中让我更多地了解它们。

I had same problem, but solved.我有同样的问题,但解决了。

I removed the following line in .bashrc我在 .bashrc 中删除了以下行

alias do="docker.exe" # this line caused the problem

I use WSL(windows subsystem for linux)我使用 WSL(用于 linux 的 windows 子系统)

In my case, what was causing the problem was an if else statement.就我而言,导致问题的原因是if else语句。 After re-writing the conditions, the error 'near done' got away.重写条件后,“接近完成”的错误消失了。

Edit your code in any linux environment then you won't face this problem.在任何 linux 环境中编辑您的代码,那么您将不会遇到这个问题。 If edit in windows notepad any space take it as ^M.如果在 Windows 记事本中编辑任何空间,请将其作为 ^M。

I have exactly the same issue as above, and took me the whole day to discover that it doesn't like my newline approach.我有与上面完全相同的问题,花了我一整天才发现它不喜欢我的换行方法。 Instead I reused the same code with semi-colon approach instead.相反,我用分号方法重用了相同的代码。 For example my initial code using the newline (which threw the same error as yours):例如,我使用换行符的初始代码(与您的错误相同):

Y=1
while test "$Y" -le "20"
do
        echo "Number $Y"
        Y=$[Y+1]
done

And using code with semicolon approach with worked wonder:并使用带有分号方法的代码来创造奇迹:

Y=1 ; while test "$Y" -le "20"; do echo "Number $Y"; Y=$[Y+1] ; done

I notice the same problem occurs for other commands as well using the newline approach, so I think I am gonna stick to using semicolon for my future code.我注意到使用换行方法的其他命令也会出现同样的问题,所以我想我会坚持在我未来的代码中使用分号。

For me you had to have it do something between the do and done.对我来说,你必须让它在做和做之间做点什么。

#!/bin/bash
echo "Endless Loop, to STOP press ctrl C or ctrl Z"

for ((; ;))
do

done
echo "Loop Ended"

gave me the error, but给了我错误,但是

#!/bin/bash

echo "Endless Loop, to STOP press ctrl C or ctrl Z"

for ((; ;))
do
     sleep 1
done
echo "Loop Ended"

fixed it.解决它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM