繁体   English   中英

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

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

知道问题可能是什么吗?

我的代码是:

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

将其保存为 .sh 并运行 bash file.sh

CentOS 6 32 位

问题是什么? 第一次使用 BASH,需要它来做一个简单的无限循环。

运行cat -v file.sh

您的文件中很可能有回车或不间断空格。 cat -v将它们分别显示为^MM-BM-M- 它同样会显示您可能已进入文件的任何其他奇怪字符。

删除 Windows 换行符

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

我在 Cygwin 上遇到了同样的错误; 我做了以下事情(其中一个修复了它):

  1. TABS转换为SPACES
  2. .(ba)sh文件上运行dos2unix

你得到什么错误?

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

如果您收到该错误,则可能有错误的行尾。 Unix 在文件末尾使用<LF>而 Windows 使用<CR><LF> <CR>字符被解释为一个字符。

您可以使用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

sp代表空格, ht代表制表符, cr代表<CR>nl代表<LF> 请注意,所有行都以cr结尾,后跟nl字符。

如果你的cat命令带有-v参数,你也可以使用cat -v test.sh

如果您的机器上有dos2unix ,您可以使用该命令来修复您的文件:

$ dos2unix test.sh

可能对其他人有帮助:当我从我做笔记的 Microsoft Word 文档中“复制粘贴”到我的 shell 脚本时,我遇到了同样的问题。

手动重写脚本中完全相同的代码就解决了这个问题。

一开始很难理解,我认为 Word 的隐藏字符和/或格式是问题所在。 明显但不可见......我为此损失了大约一个小时(我不是 shell 专家,你可能猜到了......)

有一种方法可以在没有混合换行问题的情况下解决这个问题(至少在我的 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'

这是因为 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?"

您可以通过使用反斜杠转义字符串中的反引号或使用单引号字符串来解决此问题。

我不太确定为什么这只给出一个错误消息,但我认为它与函数定义有关:

#!/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'

有时由于文件中出现意外的 CR 字符而发生此错误,通常是因为该文件是在使用 CR 行结尾的 Windows 系统上生成的。 您可以通过运行os2unixtr来解决此问题,例如:

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

这将从文件中删除任何 CR 字符。

打开名为foobar的新文件

nano -w foobar

输入脚本

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

退出并保存

CTRL + X然后YEnter

设置脚本可执行文件并运行

chmod +x foobar
./foobar

刚才有类似的问题,这些是对我有用的两个独立的实例和解决方案:

案例1。基本上,在我的换行符分隔的for循环中的最后一个命令之后有一个空格,例如。 (想象一下|这里代表文本编辑器中的克拉,显示您正在编写的位置),这是我在循环中最后一个命令的行尾单击时看到的:

for f in $pathToFiles
do
   $stuff |
done

注意克拉之前的空格(据我所知,这是cat无法在视觉上显示的东西(您可以测试的一种方法是使用od -bc yourscript.sh类的东西))。 将代码更改为

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

解决了这个问题。

案例 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; }

显然 bash 不喜欢嵌套的{} 更改为

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

在这种情况下解决了问题。 如果有人可以进一步解释其中任何一种情况,请在评论中让我更多地了解它们。

我有同样的问题,但解决了。

我在 .bashrc 中删除了以下行

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

我使用 WSL(用于 linux 的 windows 子系统)

就我而言,导致问题的原因是if else语句。 重写条件后,“接近完成”的错误消失了。

在任何 linux 环境中编辑您的代码,那么您将不会遇到这个问题。 如果在 Windows 记事本中编辑任何空间,请将其作为 ^M。

我有与上面完全相同的问题,花了我一整天才发现它不喜欢我的换行方法。 相反,我用分号方法重用了相同的代码。 例如,我使用换行符的初始代码(与您的错误相同):

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

并使用带有分号方法的代码来创造奇迹:

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

我注意到使用换行方法的其他命令也会出现同样的问题,所以我想我会坚持在我未来的代码中使用分号。

对我来说,你必须让它在做和做之间做点什么。

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

for ((; ;))
do

done
echo "Loop Ended"

给了我错误,但是

#!/bin/bash

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

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

解决它。

暂无
暂无

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

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