Man*_*nik -1 bash if-statement
if
后面是then
bash,但我不明白为什么then
不能在同一行if [...] then
中使用它,因为必须在下一行中使用它。这样可以消除代码中的歧义吗?或bash是这样设计的?其根本原因是什么?
我试着写if
,并then
在同一行,但它给了以下错误:
./test: line 6: syntax error near unexpected token \`fi'
./test: line 6: \`fi'
Run Code Online (Sandbox Code Playgroud)
代码是:
#!/bin/bash
if [ $1 -gt 0 ] then
echo "$1 is positive"
fi
Run Code Online (Sandbox Code Playgroud)
这是解释前面需要换行或分号的另一种方法:和then
之间的内容是命令(或命令序列);如果直接出现在命令后面且没有分隔符,那么是否应将其视为 shell 关键字或仅将其视为命令的参数将是不明确的。if
then
then
例如,这是一个完全有效的命令:
echo This prints a phrase ending with then
Run Code Online (Sandbox Code Playgroud)
...打印“这将打印一个以 then 结尾的短语”。现在,考虑一下这个:
if echo This prints a phrase ending with then
Run Code Online (Sandbox Code Playgroud)
then
应该打印“这打印一个以 then 结尾的短语”并稍后查找关键字,还是应该打印“这打印一个以 then 结尾的短语”并将 thethen
视为关键字?
为了解决这种歧义,shell 语法表示它应该将“then”视为 的参数echo
,并且为了将其视为关键字,您需要一个命令分隔符(换行符或分号)来标记命令的结尾。
现在,您可能认为您的if
条件[ $1 -gt 0 ]
已经有了一个完美的分隔符,即]
. 但在 shell 语法中,这实际上只是[
命令的一个参数(是的,这是一个命令)。尝试这个命令:
[ 1 -gt 0 ] then
Run Code Online (Sandbox Code Playgroud)
...你可能会得到一个类似“-bash: [: Missing ']'”的错误,因为该[
命令检查了它的最后一个参数以确保它是“]”,发现它是“then”,并且惊慌失措。
它必须在前面加上一些描述的分隔符,而不必在下一行(a)上。换句话说,要实现您想要的,您可以简单地使用:
if [[ $1 -gt 0 ]] ; then
echo "$1 is positive"
fi
Run Code Online (Sandbox Code Playgroud)
顺便说一句,对于像这样的单线,我倾向于:
[[ $1 -gt 0 ]] && echo "$1 is positive"
Run Code Online (Sandbox Code Playgroud)
但这仅仅是因为我更喜欢在屏幕上看到尽可能多的代码。这实际上只是一种样式,您可以随意忽略。
(a)可以在Bash
联机帮助页中找到原因(我强调):
保留字:保留字是对Shell具有特殊含义的字。下列单词在不加引号的情况下被识别为保留,并且是简单命令的第一个单词(请参阅下面的SHELL GRAMMAR)或
case
orfor
命令的第三个单词:
! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]]
请注意,尽管该部分指出它是“简单命令的第一个单词”,但该联机帮助页在所引用的SHELL GRAMMAR
部分中似乎与此矛盾:
一个简单的命令是一系列可选的变量分配,其后是空格分隔的单词和重定向,并由控制操作员终止。第一个单词指定要执行的命令,并作为参数零传递。
因此,是否将其视为下一个命令的一部分还是某种分隔符是有争议的。什么是不值得商榷的是,它之前需要某种形式的分离器(换行或分号,例如)then
关键字。
该手册页没有介绍为何采用这种方式设计,但可能是为了使命令的解析更简单。