我想写一个bash函数,检查文件是否具有某些属性并返回true或false。然后我可以在我的脚本中的“如果”中使用它。但是我应该返回什么呢?
function myfun(){ ... return 0; else return 1; fi;}
然后我这样使用它:
if myfun filename.txt; then ...
当然这行不通。如何才能做到这一点呢?
我想写一个bash函数,检查文件是否具有某些属性并返回true或false。然后我可以在我的脚本中的“如果”中使用它。但是我应该返回什么呢?
function myfun(){ ... return 0; else return 1; fi;}
然后我这样使用它:
if myfun filename.txt; then ...
当然这行不通。如何才能做到这一点呢?
当前回答
我遇到了一个问题(没有明确提到吗?)也就是说,不是如何返回布尔值,而是如何正确地计算它!
我想说的是如果[myfunc];然后……,但这是完全错误的。你不能使用括号!如果myfunc;然后……就是这样做的。
正如@Bruno和其他人重申的那样,真和假是命令,而不是值!这对于理解shell脚本中的布尔值非常重要。
在这篇文章中,我解释并演示了使用布尔变量:https://stackoverflow.com/a/55174008/3220983。我强烈建议你去核实一下,因为它们是如此密切相关。
在这里,我将提供一些从函数返回和计算布尔值的示例:
这样的:
test(){ false; }
if test; then echo "it is"; fi
不产生回声输出。(即false返回false)
test(){ true; }
if test; then echo "it is"; fi
生产:
it is
(即true返回true)
And
test(){ x=1; }
if test; then echo "it is"; fi
生产:
it is
因为0(即true)是隐式返回的。
现在,这就是把我搞砸的事情……
test(){ true; }
if [ test ]; then echo "it is"; fi
生产:
it is
AND
test(){ false; }
if [ test ]; then echo "it is"; fi
还生产:
it is
在这里使用括号会产生假阳性!(我推断“outer”命令的结果是0。)
从我的帖子中得到的主要信息是:不要像典型的相等检查那样使用括号来计算布尔函数(或变量),例如if [x -eq 1];然后……!
其他回答
为什么你要关心我说什么,尽管有350+个赞的答案
不是0 =真1 =假。它是:零意味着没有失败(成功),非零意味着失败(类型N)。
虽然所选的答案在技术上是“正确”的,但请不要在代码中返回1**为false。它会有一些不幸的副作用。
有经验的开发人员会把你当成业余爱好者(原因如下)。 有经验的开发人员不会这样做(原因如下)。 它很容易出错。
即使是经验丰富的开发人员也会将0和1分别误认为是假的和真的(基于上述原因)。
它需要(或会鼓励)无关紧要和荒谬的评论。 它实际上不如隐式返回状态有用。
学习一些bash
bash手册说(重点是我的)
返回[n] 导致shell函数停止执行并将值n返回给调用者。如果不提供n,则返回值为函数中执行的最后一个命令的退出状态。
因此,我们不必用0和1来表示真和假。事实上,他们这样做本质上是微不足道的知识,只对调试代码、面试问题和让新手感到惊讶有用。
bash手册还说
否则,函数的返回状态是最后执行的命令的退出状态
bash手册还说
($ ?)展开到最近执行的前台管道的退出状态。
哇,等。管道?让我们再看一遍bash手册。
管道是由一个控制操作符“|”或“|&”分隔的一个或多个命令的序列。
是的。他们说1号命令是一条管道。因此,这三句话的意思是一样的。
$ ?告诉你最后发生了什么。 它会冒出来。
我的答案
虽然@Kambus演示了这样一个简单的函数,根本不需要返回。我认为 与大多数读者的需求相比,这是不切实际的简单。
为什么回来?
如果一个函数要返回它最后一个命令的退出状态,为什么要使用return呢?因为它会导致函数停止执行。
在多种情况下停止执行
01 function i_should(){
02 uname="$(uname -a)"
03
04 [[ "$uname" =~ Darwin ]] && return
05
06 if [[ "$uname" =~ Ubuntu ]]; then
07 release="$(lsb_release -a)"
08 [[ "$release" =~ LTS ]]
09 return
10 fi
11
12 false
13 }
14
15 function do_it(){
16 echo "Hello, old friend."
17 }
18
19 if i_should; then
20 do_it
21 fi
我们这里有…
第04行是一个显式的[-ish]返回true,因为&&的RHS只有在LHS为真时才会执行
第09行返回true或false,匹配第08行的状态
第13行返回false,因为第12行
(是的,这可以打高尔夫球,但整个例子是人为的。)
另一种常见模式
# Instead of doing this...
some_command
if [[ $? -eq 1 ]]; then
echo "some_command failed"
fi
# Do this...
some_command
status=$?
if ! (exit $status); then
echo "some_command failed"
fi
Notice how setting a status variable demystifies the meaning of $?. (Of course you know what $? means, but someone less knowledgeable than you will have to Google it some day. Unless your code is doing high frequency trading, show some love, set the variable.) But the real take-away is that "if not exit status" or conversely "if exit status" can be read out loud and explain their meaning. However, that last one may be a bit too ambitious because seeing the word exit might make you think it is exiting the script, when in reality it is exiting the (...) command group subshell.
**如果你坚持使用return 1来表示false,我建议你至少使用return 255来代替。这将导致您未来的自己或任何其他必须维护您的代码的开发人员质疑“为什么是255?”这样他们至少会集中注意力,有更好的机会避免犯错。
重写一下可能有用 函数myfun(){…返回0;否则返回1;Fi;}作为这个函数myfun(){…返回;其他假;fi;}。也就是说,如果函数中的最后一条指令为false,则整个函数的结果为false,但无论如何都会返回结果为true的中断函数。我相信至少对我的bash解释器来说是这样的。
在返回之前立即使用true或false命令,然后不带参数返回。返回值将自动使用上一个命令的值。
如果不使用1或0,则为return提供参数是不一致的、特定于类型的并且容易出错。正如前面的注释所述,在这里使用1或0不是处理这个函数的正确方法。
#!/bin/bash
function test_for_cat {
if [ "$1" = "cat" ];
then
true
return
else
false
return
fi
}
for i in cat hat;
do
echo "${i}:"
if test_for_cat "${i}";
then
echo "- True"
else
echo "- False"
fi
done
输出:
$ bash bash_return.sh
cat:
- True
hat:
- False
在只使用选项-d检查目录时要小心! 如果变量$1为空,检查仍然会成功。当然,还要检查变量是否为空。
#! /bin/bash
is_directory(){
if [[ -d $1 ]] && [[ -n $1 ]] ; then
return 0
else
return 1
fi
}
#Test
if is_directory $1 ; then
echo "Directory exist"
else
echo "Directory does not exist!"
fi
继@Bruno Bronosky和@mrteatime之后,我建议你只写布尔返回“向后”。我的意思是:
foo()
{
if [ "$1" == "bar" ]; then
true; return
else
false; return
fi;
}
这样就消除了每个return语句都需要两行代码的丑陋要求。