[英]Having trouble with simple Bash if/elif/else statement
I'm writing bash scripts that need to work both on Linux and on Mac. 我正在编写需要在Linux和Mac上都可以使用的bash脚本。
I'm writing a function that will return a directory path depending on which environment I'm in. 我正在编写一个函数,该函数将根据所处的环境返回目录路径。
Here is the pseudo code: 这是伪代码:
If I'm on a Mac OS X machine, I need my function to return the path: 如果我在Mac OS X机器上,则需要我的函数来返回路径:
/usr/local/share/
Else if I'm on a Linux machine, I need my function to return the path: 否则,如果我在Linux机器上,则需要我的函数来返回路径:
/home/share/
Else, you are neither on a Linux or a Mac...sorry. 否则,您既没有使用Linux也没有使用Mac ...对不起。
I'm very new to Bash, so I apologize in advance for the really simple question. 我是Bash的新手,所以我为这个非常简单的问题向您道歉。
Below is the function I have written. 下面是我编写的函数。 Whether I'm on a Mac or Linux, it always returns
无论是在Mac还是Linux上,它总是会返回
/usr/local/share/
Please take a look and enlighten me with the subtleties of Bash. 请看一下,并以Bash的微妙之处启发我。
function get_path(){
os_type=`uname`
if [ $os_type=="Darwin" ]; then
path="/usr/local/share/"
elif [ $os_type=="Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
echo $path
} }
You need spaces around the operator in a test command: [ $os_type == "Darwin" ]
instead of [ $os_type=="Darwin" ]
. 在测试命令中,操作符周围需要空格:
[ $os_type == "Darwin" ]
而不是[ $os_type=="Darwin" ]
。 Actually, you should also use =
instead of ==
(the double-equal is a bashism, and will not work in all shells). 实际上,您还应该使用
=
而不是==
(双等号是bashism,并且不适用于所有shell)。 Also, the function
keyword is also nonstandard, you should leave it off. 另外,
function
关键字也是非标准的,您应该将其保留。 Also, you should double-quote variable references (like "$os_type"
) just in case they contain spaces or any other funny characters. 同样,您应该对变量引用(例如
"$os_type"
)加双引号,以防它们包含空格或任何其他有趣的字符。 Finally, echoing an error message ("...not supported") to standard output may confuse whatever's calling the function, because it'll appear where it expected to find a path; 最后,在标准输出中回显错误消息(“ ...不支持”)可能会使正在调用该函数的用户感到困惑,因为它会出现在期望找到路径的位置。 redirect it to standard error (
>&2
) instead. 将其重定向到标准错误(
>&2
)。 Here's what I get with these cleaned up: 这是我清理后得到的结果:
get_path(){
os_type=`uname`
if [ "$os_type" = "Darwin" ]; then
path="/usr/local/share/"
elif [ "$os_type" = "Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported" >&2
exit 1
fi
echo "$path"
}
EDIT: My explanation of the difference between assignments and comparisons got too long for a comment, so I'm adding it here. 编辑:我对赋值和比较之间的区别的解释太长了,无法发表评论,因此我在此处添加了它。 In many languages, there's a standard expression syntax that'll be the same when it's used independently vs. in test.
在许多语言中,有一种标准的表达式语法,当单独使用它与在测试中使用时,它将是相同的。 For example, in C
a = b
does the same thing whether it's alone on a line, or in a context like if ( a = b )
. 例如,在C中,无论
a = b
是单独出现在一行上还是在if ( a = b )
这样的上下文中, a = b
都可以执行相同的操作。 The shell isn't like that -- its syntax and semantics vary wildly depending on the exact context, and it's the context (not the number of equal signs) that determines the meaning. 外壳不是那样的-它的语法和语义根据确切的上下文而千差万别,而上下文(而不是等号的数量)决定了含义。 Here are some examples:
这里有些例子:
a=b
by itself is an assignment a=b
本身就是一个赋值 a = b
by itself will run a
as a command, and pass it the arguments "=" and "b". a = b
本身将作为命令运行a
,并向其传递参数“ =”和“ b”。 [ a = b ]
runs the [
command (which is a synonym for the test
command) with the arguments "a", "=", "b", and "]" -- it ignores the "]", and parses the others as a comparison expression. [ a = b ]
使用参数“ a”,“ =“,“ b”和“]”运行[
命令(这是test
命令的同义词)–它忽略“]”,并解析其他作为比较表达式。 [ a=b ]
also runs the [
( test
) command, but this time after removing the "]" it only sees a single argument, "a=b" -- and when test
is given a single argument it returns true if the argument isn't blank, which this one isn't. [ a=b ]
也运行[
( test
)命令,但是这一次在删除“]”之后,它只会看到一个参数“ a = b”-当给test
一个参数时,如果参数不是空白,而这个不是。 bash's builtin version of [
( test
) accepts ==
as a synonym for =
, but not all other versions do. bash的内置版本
[
( test
)接受==
作为=
的同义词,但并非所有其他版本都支持。
BTW, just to make things more complicated bash also has [[ ]]
expressions (like test
, but cleaner and more powerful) and (( ))
expressions (which are totally different from everything else), and even ( )
(which runs its contents as a command, but in a subshell). 顺便说一句,只是为了使事情变得更复杂,bash还具有
[[ ]]
表达式(如test
,但更简洁,功能更强大)和(( ))
表达式(与其他事物完全不同),甚至还有( )
(运行它的内容作为命令,但在子外壳中)。
You need to understand what [
means. 您需要了解
[
意思。 Originally, this was a synonym for the /bin/test
command. 最初,这是
/bin/test
命令的同义词。 These are identical: 这些是相同的:
if test -z "$foo"
then
echo "String '$foo' is null."
fi
if [ -z "$foo" ]
then
echo "String '$foo' is null."
fi
Now, you can see why spaces are needed for all of the parameters . 现在,您可以了解为什么所有参数都需要空格。 These are parameters and not merely boolean expressions.
这些是参数 ,而不仅仅是布尔表达式。 In fact, the test manpage is a great place to learn about the various tests.
实际上, 测试手册页是了解各种测试的好地方。 (Note: The
test
and [
are built in commands to the BASH shell.) (注意:
test
和[
是BASH shell的内置命令。)
if [ $os_type=="Darwin" ]
then
This should be three parameters: 这应该是三个参数:
"$os_type"
=
and not ==
=
而非==
"Darwin"
if [ "$os_type" = "Darwin" ] # Three parameters to the [
command then 如果[“$操作系统类型” =“达尔文”]#三个参数到
[
命令然后
If you use single square brackets, you should be in the habit to surround your parameters with quotation marks. 如果使用单个方括号,则应该习惯于用引号将参数引起来。 Otherwise, you will run into trouble:
否则,您将遇到麻烦:
foo="The value of FOO"
bar="The value of BAR"
if [ $foo != $bar ] #This won't work
then
...
In the above, the shell will interpolate $foo
and $bar
with their values before evaluating the expressions. 在上面的代码中,shell在评估表达式之前将其值插入
$foo
和$bar
。 You'll get: 你会得到:
if [ The value of FOO != The value of BAR ]
The [
will look at this and realize that neither The
or value
are correct parameters, and will complain. [
将查看此内容,并意识到The
或value
都不是正确的参数,并且会抱怨。 Using quotes will prevent this: 使用引号可以防止这种情况:
if [ "$foo" != "$bar" ] #This will work
then
This becomes: 变成:
if [ "The value of FOO" != "The value of BAR" ]
This is why it's highly recommended that you use double square brackets for your tests: [[ ... ]]
. 这就是为什么强烈建议您在测试中使用双方括号:
[[ ... ]]
。 The test looks at the parameters before the shell interpolates them: 该测试在外壳程序对参数进行插值之前先检查它们:
if [[ $foo = $bar ]] #This will work even without quotation marks
Also, the [[ ... ]]
allows for pattern matching: 另外,
[[ ... ]]
允许模式匹配:
if [[ $os_type = D* ]] # Single equals is supported
then
path="/usr/local/share/"
elif [[ $os_type == L* ]] # Double equals is also supported
then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
This way, if the string is Darwin32
or Darwin64
, the if
statement still functions. 这样,如果字符串是
Darwin32
或Darwin64
,则if
语句仍然起作用。 Again, notice that there has to be white spaces around everything because these are parameters to a command (actually, not anymore, but that's the way the shell parses them). 再次注意,所有内容周围都必须有空格,因为这些是命令的参数(实际上已经不复存在了,但这是Shell解析它们的方式)。
Adding spaces between the arguments for the conditionals fixed the problem. 在条件的参数之间添加空格可解决此问题。
This works 这有效
function get_path(){
os_type=`uname`
if [ $os_type == "Darwin" ]; then
path="/usr/local/share/"
elif [ $os_type == "Linux" ]; then
path="/home/share/"
else
echo "${os_type} is not supported"
exit 1
fi
echo $path
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.