在Bash中,if、elif和else语句存在的问题

434

我似乎无法弄清楚以下if语句中涉及elifthen的问题。请注意,printf仍在开发中,我还没有能够在语句中测试它,所以很可能是错误的。

我收到的错误信息是:

./timezone_string.sh: line 14: syntax error near unexpected token `then'
./timezone_string.sh: line 14: `then'

而且陈述就是这样。

if [ "$seconds" -eq 0 ];then
   $timezone_string="Z"
elif[ "$seconds" -gt 0 ]
then
   $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
else
   echo "Unknown parameter"
fi

10
我想知道为什么在ifelif语句中需要then,而在else中不需要,在一般情况下也是如此。 - user4104817
3
@w17t,因为我们需要将条件与序列分开。 - Sasha
5
@codeforester,我认为将一个有500K次浏览量的问题标记为重复问题并与一个仅有5K次浏览量的问题合并在一起并没有太多逻辑。 - fedorqui
使用一些代码自动格式化工具可能会帮助您自动在括号周围添加/删除空格。您可以搜索编辑器的插件。 - Nj Subedi
对我来说,我从未想过在“if”语句后面加上分号再跟着“then”。你的问题本身就是我的解决方案。非常感谢!! - Shan
5个回答

535

elif[之间缺少一个空格:

elif[ "$seconds" -gt 0 ]

应该是

elif [ "$seconds" -gt 0 ]

总的来说,要遵循的语法是:

if [ conditions ]; then
   # Things
elif [ other_conditions ]; then
   # Other things
else
   # In case none of the above occurs
fi

我注意到这个问题得到了很多浏览,需要指出的是要遵循以下语法:

if [ conditions ]
# ^ ^          ^

这意味着括号周围需要留出空格。否则它将不起作用。这是因为 [ 本身就是一个命令。

你没有看到像 elif [: 命令未找到(或类似的)一样的东西,原因在于,在看到 ifthen 后,shell 正在寻找 elifelsefi。但它发现另一个 then (在格式不正确的 elif[ 之后)。只有在解析语句后才会执行该语句(并输出像 elif [: 命令未找到 这样的错误消息)。


38
括号需要空格的原因是因为它们只是实际程序的快捷方式(至少第一个括号是这样,据我所知第二个只是语法糖)。要理解其含义,请参阅左方括号的实际手册: "$ man ["。 - Michael Johansen
4
这篇帖子不应该被标记为打字错误而关闭吗? - zx8754
3
@zx8754本来可能成为修复此错误的权威方法,但现在已经成为了一个相当有用的方法(观看次数已达360,000次且仍在增加)。 - fedorqui
4
我的一些同事不理解“空格”或“代码风格”的概念,因此这可能不是一个打字错误。 - juzzlin
3
“test”是“if”的一种别名,这就是为什么需要空格的原因。 if test "$seconds" -eq 0; then ... fi 等同于 if [ "$seconds" -eq 0 ]; then ... fi]。如果你需要更多信息,请参考命令“man test”。 - Melicerte
显示剩余2条评论

342

您的脚本存在一些语法问题。这是修正后的版本:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

92
有趣的是,这是我在 StackExchange 上找到的唯一完整而且简单的“if-then-else” bash 结构...谢谢。 - Wildcard
1
缩进是可选的。解释器可以(而且应该)是#!/bin/sh - user4104817
3
完全胡说,翻译器可能是#!/bin/sh,但不一定是。 - Camusensei
5
@Camusensei,这不完全是无稽之谈,因为sh可用于提高兼容性(并非所有*nix发行版都默认使用[tag:bash]作为默认shell(有些使用ksh或ash,但大多数确实依赖标准的sh来运行)。此外,如果脚本中未使用bash的特定或高级功能,则应使用'sh'作为解释器(这是另一个原因),因为它可以单独处理脚本。 - user4104817
8
没错,我这边用词不当。 - Camusensei

28

[是一个命令(或者在某些shell中是内置的)。它必须与前面的语句通过空格分隔:

elif [

4
它已被bash内置命令所取代,但您的信息仍然是正确的。使用type -a [来查看。 - Camusensei
这也是一个二进制文件,这对我来说总是感觉很奇怪。 - mr.zog

9

我建议您查看bash中的条件语句基础。

符号"["是一个命令,必须在它之前加上一个空格。如果您在elif后没有留下空格,系统会将elif[解释为一个特定的命令,这绝对不是您此时想要的。

用法:

elif(A COMPULSORY WHITESPACE WITHOUT PARENTHESIS)[(A WHITE SPACE WITHOUT PARENTHESIS)conditions(A WHITESPACE WITHOUT PARENTHESIS)]

简而言之,编辑您的代码段如下所示:
elif [ "$seconds" -gt 0 ]

您的代码没有编译错误就可以了。最终代码段应该如下所示:
#!/bin/sh    
if [ "$seconds" -eq 0 ];then
       $timezone_string="Z"
    elif [ "$seconds" -gt 0 ]
    then
       $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
    else
       echo "Unknown parameter"
    fi

6

在您的程序中,elif[之间缺少空格。您需要进行更正并检查一下。这是已经修复的程序:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

与此相关的有用链接 bash if else 语句


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接