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

时间:2013-08-21 21:06:33

标签: bash

知道问题可能是什么?

我的代码是:

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

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

CentOS 6 32位

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

12 个答案:

答案 0 :(得分:25)

运行cat -v file.sh

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

使用

删除Windows换行符
tr -d '\r' < file.sh > fixedfile.sh

答案 1 :(得分:10)

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

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

答案 2 :(得分:4)

你得到的错误是什么?

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

如果您收到该错误,则可能会出现错误的行结尾。当Windows使用<LF>时,Unix在文件末尾使用<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 test.sh命令采用cat参数,您也可以使用-v

如果您的信箱上有dos2unix,则可以使用该命令修复您的文件:

$ dos2unix test.sh

答案 3 :(得分:3)

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

  

tr -d&#39; \ 015&#39; &LT; yourscript.sh&gt; newscript.sh

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

答案 4 :(得分:2)

打开名为 foobar

的新文件
nano -w foobar

输入脚本

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

退出并保存

CTRL + X 然后 Y 输入

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

chmod +x foobar
./foobar

答案 5 :(得分:2)

可以帮助别人:我在做了一些&#34;复制粘贴&#34;时遇到了同样的问题。从Microsoft Word文档,我记笔记,到我的shell脚本。

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

起初这是不可理解的,我认为Word的隐藏字符和/或格式是问题所在。明显但不可见......我在这上面失去了一个小时(我没有贝壳专家,你可能会猜到......)

答案 6 :(得分:0)

在任何Linux环境中编辑代码,然后您将不会遇到此问题。如果在Windows中编辑 记事本任何空间都将其视为^ M.

答案 7 :(得分:0)

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

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

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

答案 8 :(得分:0)

有一种方法可以在没有混合换行问题的情况下解决这个问题(至少在我的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在双引号字符串中扩展反引号(请参阅quotingcommand substitution上的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'

答案 9 :(得分:0)

现在有类似的问题,这是对我有用的两个单独的实例和解决方案:

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

for f in $pathToFiles
do
   $stuff |
done

请注意克拉之前的空间(据我所知,cat尚无法以视觉方式显示(您可以 进行测试的一种方式是使用{{ 1}})。将代码更改为

od -bc yourscript.sh

解决了这个问题。

案例2。正在为for循环使用伪try-catch块(请参见https://stackoverflow.com/a/22010339/8236733),例如

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

,显然bash不喜欢嵌套的{ for f in $pathToFiles do { $stuff } || { echo "Failed to complete stuff"; exit 255; } done } || { echo "Failed to complete loop"; exit 255; } 。更改为

{}

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

答案 10 :(得分:0)

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

我在.bashrc中删除了以下行

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

我使用WSL(Linux的Windows子系统)

答案 11 :(得分:0)

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