我想编写一个Bash函数来检查文件是否具有某些属性,并返回true或false。然后我可以在我的脚本中使用它在"if"语句中。但是我应该返回什么?
function myfun(){ ... return 0; else return 1; fi;}
然后我像这样使用它:
if myfun filename.txt; then ...
当然这行不通。如何实现?
使用0表示真,使用1表示假。
示例:
#!/bin/bash
isdirectory() {
if [ -d "$1" ]
then
# 0 = true
return 0
else
# 1 = false
return 1
fi
}
if isdirectory $1; then echo "is directory"; else echo "nopes"; fi
编辑
根据@amichair的评论,这些也是可能的选项。
isdirectory() {
if [ -d "$1" ]
then
true
else
false
fi
}
isdirectory() {
[ -d "$1" ]
}
[ -d "$1" ]
。 - amichair这并不是说0 = true
和1 = false
。实际上是:零意味着没有失败(成功),而非零意味着失败(类型N的失败)。
虽然被选中的回答在技术上是"true",但请不要在你的代码中使用return 1
**表示false。这会带来一些不幸的副作用。
bash手册中提到(重点在我)
return [n]
使一个shell函数停止执行,并将值n返回给调用者。 如果未提供n,则返回值是函数中最后执行的命令的退出状态。
因此,我们永远不必使用0和1来表示真和假。它们这样做的事实基本上是琐碎的知识,仅用于调试代码、面试问题和让新手大吃一惊。
bash手册还提到
否则,函数的返回状态是最后执行的命令的退出状态
bash手册还提到
($?)扩展为最近执行的前台管道的退出状态。return
。但我认为这对于大多数读者来说过于简单了。return
?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
&&
的右侧只有在左侧为true时才会执行。# 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
status
变量来解释$?
的含义。(当然,你知道$?
是什么意思,但是比你不那么了解的人可能会在某一天需要通过谷歌来查找。除非你的代码是在进行高频交易,表达一些爱意,设置这个变量。)但真正的要点是,"如果不是退出状态"或者相反地"如果是退出状态"可以大声朗读并解释它们的含义。然而,最后一个可能有点过于雄心勃勃,因为看到exit
这个词可能会让你认为它是退出脚本,而实际上它是退出(...)
命令组子shell。
return 1
来表示假,我建议你至少使用return 255
代替。这会让你未来的自己或其他必须维护你代码的开发人员产生疑问:“为什么是255?”然后他们至少会注意到并更有可能避免“1=true,0=false”的错误。**return 1
。假设我有一个 validate
函数,如果验证失败,我认为 return 1
是合理的。毕竟,这是停止脚本执行的原因,如果没有得到适当处理(例如,当使用 set -e
时)。 - JepZreturn 1
没有任何问题...特别是如果您不想引用先前的命令。这样做并不意味着您自动成为“业余爱好者”... - Akitomyfun(){
[ -d "$1" ]
}
if myfun "path"; then
echo yes
fi
# or
myfun "path" && echo yes
使用 -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
$1
周围添加适当的引用("$1"
),那么您就不需要检查空变量了。[[ -d "$1" ]]
会失败,因为""
不是一个目录。 - morgents[[
... ]]
中,引号没有任何区别。而在 [
...]
中,它当然会有所不同,因为如果变量扩展为空并被省略,那么就只剩下了 [ -d ]
,它只是测试 -d
是否为非空字符串;这当然是正确的。 - Martin Kealey在你的return
之前立即使用true
或false
命令,然后return
没有参数。 return
将自动使用您最后一个命令的值。
向return
提供参数是不一致的、类型特定的,并且容易出错,如果您不使用1或0的话。正如先前的评论所述,在此处使用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
if test_for_cat 'snow leopard' ; then echo "It's a feline" ; else echo "It's something else" ; fi
调用时不会产生奇怪的错误。 - Martin Kealeysh
标准,否则应始终使用[[
而不是[
。请参见:https://mywiki.wooledge.org/BashFAQ/031 - Bruno Bronosky为了代码可读性,我认为返回true/false应该:
return
后跟另一个关键字(true
或false
)我的解决方案是如下所示:return $(true)
或 return $(false)
is_directory()
{
if [ -d "${1}" ]; then
return $(true)
else
return $(false)
fi
}
TRUE=0; FALSE=1
,然后使用return $TRUE
或return $FALSE
会是更好的答案。在大多数情况下,代码可读性比轻微的性能提升更重要,因此使用bash脚本。如果需要性能和优化,则bash不是答案。 - RandomName$(true)
和 $(false)
,因为它违反了另一个重要的风格规则:_始终引用扩展_。总有一天,有人会查看 ShellCheck 的结果,并通过将 return $(true)
更改为 return "$(true)"
来“修复”此代码。这不是语法错误,但是由于空字符串不是数字,因此将导致 return
报错 需要数字参数
。 - Martin Kealeyreturn $TRUE
的方法,因为它不会创建子shell。因此,由于我非常重视代码的可读性,我发誓永远不会使用 return "$TRUE"
只是为了满足一些在线工具的要求。 - RandomName我遇到了一个问题(可能还没有明确提到?),让我感到困惑。那就是,不是如何“返回”布尔值,而是如何正确地评估它!
我试图这样写if [ myfunc ]; then ...
,但那是错误的。你不能使用括号!if myfunc; then ...
才是正确的方法。
正如 @Bruno 和其他人所重申的,true
和false
都是命令,而不是值!这对于理解shell脚本中的布尔值非常重要。
在这篇文章中,我解释并演示了如何使用布尔变量:https://dev59.com/j3A85IYBdhLWcg3wEPVL#55174008。我强烈建议查看一下,因为它与这个主题非常相关。
在这里,我将提供一些从函数中返回和“评估”布尔值的示例:
这段代码:
test(){ false; }
if test; then echo "it is"; fi
不会产生回显输出。(例如false
返回 false)
test(){ true; }
if test; then echo "it is"; fi
产生:
it is
true
返回 true)
另外,
test(){ x=1; }
if test; then echo "it is"; fi
生成:
it is
test(){ true; }
if [ test ]; then echo "it is"; fi
生成:
it is
并且
test(){ false; }
if [ test ]; then echo "it is"; fi
ALSO产生:
it is
在这里使用方括号产生了一个错误的Positive!(我推断"外部"命令的结果为0。)
我的主要观点是:不要像对典型的相等检查一样,使用括号来评估布尔函数(或变量),例如if [ x -eq 1 ]; then...
!
test
函数包含了一个printf
,你就会注意到从[ test ]
中缺少输出。规则非常简单:[
不是if
结构固有语法的一部分;相反,它接受一系列命令,而[
是一个(奇怪命名的)命令。顺便说一下,将函数命名为test
是个坏主意,因为test
是一个内置函数(等同于[
)。 - Martin Kealey在跟进 @Bruno Bronosky 和 @mrteatime 之后,我提供了一种建议,那就是你只需将布尔返回值“反过来”写即可。我的意思是:
foo()
{
if [ "$1" == "bar" ]; then
true; return
else
false; return
fi;
}
我发现测试函数输出的最短形式就是:
do_something() {
[[ -e $1 ]] # e.g. test file exists
}
do_something "myfile.txt" || { echo "File doesn't exist!"; exit 1; }
true
/false
,或使用true; return
提前退出。请看以下内容:function is_true() { true; }
if is_true; then echo 'true is true'; fi
if ! is_true; then exit; else echo '! true is ! true'; fi
function is_false() { false; }
if ! is_false; then echo 'false is false'; fi
if is_false; then exit; else echo '! false is ! false'; fi
(true; echo $?)
。这也适用于嵌套函数(请参见下一节)。function from_var() {
local input=$1
local my_var
if ((input == 1)); then
my_var=$(true; echo $?)
else
my_var=$(false; echo $?)
fi
echo 'ignore this line'
(exit $my_var)
}
if from_var 1; then echo "return true is true"; else exit; fi
if from_var 0; then exit; else echo "return false is false"; fi
/dev/null
,否则结果可能也会包含来自echo
或其他命令的字符串。请注意,在if
语句中的(exit $rval)
可让您正确解释返回值。其他方法如if (($rval))
或if [ $rval ]
将无法按预期工作。# Return a truthy result
rval=$(from_var 1 >/dev/null; echo $?)
if (exit $rval); then echo "return true as variable is true"; else exit; fi
# Return a falsy result
rval=$(from_var 0 >/dev/null; echo $?)
if (exit $rval); then exit; else echo "return false as variable is false"; fi
true is true
! true is ! true
false is false
! false is ! false
ignore this line
return true is true
ignore this line
return false is false
return true as variable is true
return false as variable is false
如果您不想使用> /dev/null
在函数内部抑制输出,则可以重写为先调用该函数。
from_var 0; rval="$?"
if
语句关注的是myfun
的零退出状态:如果myfun
以0
退出,则执行then ...
;否则,执行else ...
。 - Eelvexfunction
关键字是Bash独有的语法,会在其他一些shell中导致语法错误。基本上,它要么是不必要的,要么是被禁止的,所以为什么要使用它呢?甚至作为grep的搜索目标都没有用,因为可能根本不存在(可以搜索()
代替)。 - Gordon Davisson