【问题标题】:Confusing syntax error near unexpected token 'done'意外标记“完成”附近令人困惑的语法错误
【发布时间】:2012-05-19 00:52:36
【问题描述】:

我正在尝试学习 shell 脚本,所以我创建了一个简单的脚本,其中包含一个什么都不做的循环:

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

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

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

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

【问题讨论】:

标签: bash shell syntax for-loop syntax-error


【解决方案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)

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • : 是正确的无操作,但 'true' 长期以来一直是内置的。我想今天使用的 shell 很少会产生一个新进程。
    • Bash : 就像 Python pass 指令
    • 还要注意(5 年后),: 是 POSIX 要求内置的,而 true 只是可选的(但我几乎打赌总是)一个内置的。
    【解决方案3】:

    dashbash 在这种情况下有点脑残,它们不允许空循环,因此您需要添加 no op 命令来使其运行,例如true:。我的测试表明: 更快一点,although they should be the same,不知道为什么:

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

    【讨论】:

    • 我将不处理空循环称为一项功能! ;-) 祝大家好运。
    • @shellter: 不处理就好,做语法错误就不行
    【解决方案4】:

    不,shell 脚本对制表符不敏感(除非你做了一些非常疯狂的事情,在这个例子中你没有这样做)。

    你不能有一个空的while do done 块,(cmets 不算) 尝试替换为echo $name

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

    输出

    test test2 test3 test4
    

    【讨论】:

    • 感谢有效 =),有没有办法让我在一行中获得所有输出?
    • 请注意,echo 非常方便地打印原始示例所示的逐行数据。了解printf(在此处搜索 S.O. 以获取示例),因为它在格式化数据打印方面非常强大且灵活。祝你好运。
    • 一个有效的“no-op”命令是:
    • @glennjackman :是的,好点。正如 fenerlitk 所说的“我正在尝试学习 shell 脚本”,我认为他/她希望看到循环在起作用是有道理的。 Fenerlitk,请注意,':' no-op 命令可能已放入您的循环中,在您发表评论之前,即: # do something,并且该循环将完成,但您不会看到任何事情发生。祝大家好运。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      你可以用 'true' 代替空。

      【讨论】:

        猜你喜欢
        • 2011-08-02
        • 2015-05-10
        • 2015-01-01
        • 2018-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多