6

我正在尝试学习 shell 脚本,所以我创建了一个简单的脚本,其中包含一个不执行任何操作的循环:

#!/bin/bash
names=(test test2 test3 test4)
for name in ${names[@]}
do
        #do something
done

但是,当我运行此脚本时,出现以下错误:

./test.sh:第 6 行:意外标记附近的语法错误完成'
./test.sh:第 6 行:完成'

我在这里错过了什么?shell 脚本是“标签敏感的”吗?

4

6 回答 6

7

不,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
于 2012-05-10T12:51:16.840 回答
6

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 次运行的平均值。

于 2012-05-10T12:52:18.940 回答
4

Bash 有一个内置的 no-op,即冒号 (:),它比生成另一个进程来运行更轻量级true

#!/bin/bash
names=(test test2 test3 test4)
for name in "${names[@]}"
do
    :
done

编辑:威廉正确地指出这true也是一个内置的外壳,所以把这个答案作为另一个选项仅供参考,不是比使用 true 更好的解决方案。

于 2012-05-10T13:16:10.503 回答
1

你可以用'true'代替nothing。

于 2012-05-10T12:42:49.130 回答
1

你需要在你的循环中有一些东西,否则 bash 会抱怨。

于 2012-05-10T12:52:39.143 回答
1

某些版本的 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)

于 2017-11-18T12:27:32.930 回答