35

知道问题可能是什么吗?

我的代码是:

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

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

CentOS 6 32 位

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

4

12 回答 12

42

运行cat -v file.sh

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

删除 Windows 换行符

tr -d '\r' < file.sh > fixedfile.sh
于 2013-08-22T00:23:16.787 回答
12

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

  1. 转换TABSSPACES
  2. dos2unix.(ba)sh文件上运行
于 2015-11-02T02:29:40.713 回答
7

你得到什么错误?

$ 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 test.sh如果您的cat命令带有-v参数,您也可以使用。

如果你有dos2unix你的盒子,你可以使用该命令来修复你的文件:

$ dos2unix test.sh
于 2013-08-22T00:41:59.370 回答
4

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

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

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

于 2015-05-28T18:41:20.730 回答
4

有一种方法可以在没有混合换行问题的情况下解决这个问题(至少在我的 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'
于 2016-10-17T03:27:37.387 回答
4

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

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

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

于 2017-02-27T06:05:32.100 回答
2

打开名为的新文件 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
于 2013-08-22T02:52:51.697 回答
1

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

案例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 不喜欢嵌套{}的 s。更改为

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

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

于 2018-09-17T20:37:41.643 回答
1

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

我在 .bashrc 中删除了以下行

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

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

于 2019-03-05T13:47:24.970 回答
0

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

于 2014-02-04T05:36:00.870 回答
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

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

于 2014-12-15T23:17:59.910 回答
0

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

于 2020-11-02T01:02:38.263 回答