bash 意外标记“完成”附近令人困惑的语法错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10534186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Confusing syntax error near unexpected token 'done'
提问by fenerlitk
I am trying to learn shell scripting, so I created a simple script with a loop that does nothing:
我正在尝试学习 shell 脚本,所以我创建了一个简单的脚本,其中包含一个什么都不做的循环:
#!/bin/bash
names=(test test2 test3 test4)
for name in ${names[@]}
do
#do something
done
however, when I run this script I get the following errors:
但是,当我运行此脚本时,出现以下错误:
./test.sh: line 6: syntax error near unexpected token done'
./test.sh: line 6: done'
./test.sh:第 6 行:意外标记附近的语法错误完成'
./test.sh:第 6 行:完成'
What have I missed here? are shell scripts 'tab sensitive'?
我在这里错过了什么?shell 脚本是否“标签敏感”?
回答by shellter
No, shell scripts are not tab sensitive (unless you do something really crazy, which you are not doing in this example).
不,shell 脚本不是标签敏感的(除非你做了一些非常疯狂的事情,你在这个例子中没有做)。
You can't have an empty while do done
block, (comments don't count)
Try substituting echo $name
instead
你不能有一个空while do done
块,(注释不计)尝试代echo $name
代替
#!/bin/bash
names=(test test2 test3 test4)
for name in ${names[@]}
do
printf "%s " $name
done
printf "\n"
output
输出
test test2 test3 test4
回答by Thor
dash
and bash
are a bit brain-dead in this case, they do not allow an empty loop so you need to add a no op command to make this run, e.g. true
or :
. My tests suggest the :
is a bit faster, although they should be the same, not sure why:
dash
并且bash
在这种情况下有点脑残,它们不允许空循环,因此您需要添加 no op 命令来运行此命令,例如true
或:
。我的测试表明:
有点快,虽然它们应该是一样的,但不知道为什么:
time (i=100000; while ((i--)); do :; done)
n average takes 0.262
seconds, while:
n 平均需要0.262
几秒钟,而:
time (i=100000; while ((i--)); do true; done)
takes 0.293
seconds. Interestingly:
需要0.293
几秒钟。有趣的是:
time (i=100000; while ((i--)); do builtin true; done)
takes 0.356
seconds.
需要0.356
几秒钟。
All measurements are an average of 30 runs.
所有测量均为 30 次运行的平均值。
回答by chepner
Bash has a built-in no-op, the colon (:), which is more lightweight
than spawning another process to run true
.
Bash 有一个内置的空操作,即冒号 (:),它比生成另一个进程运行更轻量级true
。
#!/bin/bash
names=(test test2 test3 test4)
for name in "${names[@]}"
do
:
done
EDIT: William correctly points out that true
is also a shell built-in, so take this answer as just another option FYI, not a better solution than using true.
编辑:威廉正确地指出这true
也是一个内置的外壳,所以把这个答案作为另一个选项仅供参考,不是比使用 true 更好的解决方案。
回答by Dror Harari
This error is expected with some versions of bash where the script was edited on Windows and so the script actually looks as follows:
某些版本的 bash 会出现此错误,其中脚本是在 Windows 上编辑的,因此脚本实际上如下所示:
#!/bin/bash^M
names=(test test2 test3 test4)^M
for name in ${names[@]}^M
do^M
printf "%s " $name^M
done^M
printf "\n"^M
where the ^M represents the carriage-return character (0x0D). This can easily be seen in vi by using the binary option as in:
其中 ^M 代表回车符 (0x0D)。这可以通过使用二进制选项在 vi 中轻松看到,如下所示:
vi -b script.sh
To remove those carriage-return characters simply use the vi command:
要删除这些回车符,只需使用 vi 命令:
1,$s/^M//
(note that the ^M above is a single carriage-return character, to enter it in the editor use sequence Control-V Control-M)
(注意上面的 ^M 是单个回车符,要在编辑器中输入它,请使用序列 Control-V Control-M)
回答by Ja?ck
You could replace the nothing with 'true' instead.
你可以用'true'代替nothing。
回答by Douglas Leeder
You need to have something in your loop otherwise bash complains.
你需要在你的循环中加入一些东西,否则 bash 会抱怨。