我正在尝试学习 shell 脚本,所以我创建了一个简单的脚本,其中包含一个不执行任何操作的循环:
#!/bin/bash
names=(test test2 test3 test4)
for name in ${names[@]}
do
#do something
done
但是,当我运行此脚本时,出现以下错误:
./test.sh:第 6 行:意外标记附近的语法错误完成'
./test.sh:第 6 行:完成'
我在这里错过了什么?shell 脚本是“标签敏感的”吗?
我正在尝试学习 shell 脚本,所以我创建了一个简单的脚本,其中包含一个不执行任何操作的循环:
#!/bin/bash
names=(test test2 test3 test4)
for name in ${names[@]}
do
#do something
done
但是,当我运行此脚本时,出现以下错误:
./test.sh:第 6 行:意外标记附近的语法错误完成'
./test.sh:第 6 行:完成'
我在这里错过了什么?shell 脚本是“标签敏感的”吗?
不,shell 脚本对制表符不敏感(除非你做了一些非常疯狂的事情,在这个例子中你没有这样做)。
你不能有一个空while do done块,(评论不计)尝试echo $name替换
#!/bin/bash
names=(test test2 test3 test4)
for name in ${names[@]}
do
printf "%s " $name
done
printf "\n"
输出
test test2 test3 test4
dash并且bash在这种情况下有点脑残,它们不允许空循环,因此您需要添加 no op 命令以使其运行,例如trueor :。我的测试表明:速度要快一些,尽管它们应该是相同的,但不知道为什么:
time (i=100000; while ((i--)); do :; done)
n 平均需要0.262几秒钟,而:
time (i=100000; while ((i--)); do true; done)
需要0.293几秒钟。有趣的是:
time (i=100000; while ((i--)); do builtin true; done)
需要0.356几秒钟。
所有测量都是 30 次运行的平均值。
Bash 有一个内置的 no-op,即冒号 (:),它比生成另一个进程来运行更轻量级true。
#!/bin/bash
names=(test test2 test3 test4)
for name in "${names[@]}"
do
:
done
编辑:威廉正确地指出这true也是一个内置的外壳,所以把这个答案作为另一个选项仅供参考,不是比使用 true 更好的解决方案。
你可以用'true'代替nothing。
你需要在你的循环中有一些东西,否则 bash 会抱怨。
某些版本的 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
其中 ^M 表示回车符 (0x0D)。这可以通过使用二进制选项在 vi 中轻松看到,如下所示:
vi -b script.sh
要删除这些回车符,只需使用 vi 命令:
1,$s/^M//
(注意上面的 ^M 是单个回车符,要在编辑器中输入它使用序列 Control-V Control-M)