从 Bash 函数返回一个布尔值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5431909/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:19:43  来源:igfitidea点击:

Returning a boolean from a Bash function

bashshellboolean

提问by luca

I want to write a bash function that check if a file has certain properties and returns true or false. Then I can use it in my scripts in the "if". But what should I return?

我想编写一个 bash 函数来检查文件是否具有某些属性并返回 true 或 false。然后我可以在“if”的脚本中使用它。但是我应该返回什么?

function myfun(){ ... return 0; else return 1; fi;}

then I use it like this:

然后我像这样使用它:

if myfun filename.txt; then ...

of course this doesn't work. How can this be accomplished?

这当然行不通。如何做到这一点?

回答by Erik

Use 0 for true and 1 for false.

使用 0 表示真,1 表示假。

Sample:

样本:

#!/bin/bash

isdirectory() {
  if [ -d "" ]
  then
    # 0 = true
    return 0 
  else
    # 1 = false
    return 1
  fi
}


if isdirectory ; then echo "is directory"; else echo "nopes"; fi

Edit

编辑

From @amichair's comment, these are also possible

从@amichair 的评论来看,这些也是可能的

isdirectory() {
  if [ -d "" ]
  then
    true
  else
    false
  fi
}


isdirectory() {
  [ -d "" ]
}

回答by Bruno Bronosky

Why you should care what I say in spite of there being a 250+ upvote answer

尽管有 250 多个赞成票的答案,但为什么你应该关心我说的话

It's not that 0 = trueand 1 = false. It is: zero means no failure (success)and non-zero means failure (of type N).

不是那个0 = true1 = false。它是:零表示没有失败(成功)非零表示失败(N 型)

While the selected answeris technically "true" pleasedo not put return 1** in your code for false. It will have several unfortunate side effects.

虽然所选答案在技​​术上是“真”,但不要return 1在您的代码中为false放置** 。它将有几个不幸的副作用。

  1. Experienced developers will spot you as an amateur (for the reason below).
  2. Experienced developers don't do this (for all the reasons below).
  3. It is error prone.
    • Even experienced developers can mistake 0 and 1 as false and true respectively (for the reason above).
  4. It requires (or will encourage) extraneous and ridiculous comments.
  5. It's actually less helpful than implicit return statuses.
  1. 有经验的开发人员会将您视为业余爱好者(原因如下)。
  2. 有经验的开发人员不会这样做(出于以下所有原因)。
  3. 它很容易出错。
    • 即使是有经验的开发人员也可能将 0 和 1 分别误认为 false 和 true(出于上述原因)。
  4. 它需要(或将鼓励)无关紧要和荒谬的评论。
  5. 它实际上不如隐式返回状态有用。

Learn some bash

学习一些 bash

The bash manualsays (emphasis mine)

bash的手册说(重点煤矿)

return [n]

Cause a shell function to stop executing and return the value n to its caller. If n is not supplied, the return value is the exit status of the last command executedin the function.

返回 [n]

导致 shell 函数停止执行并将值 n 返回给它的调用者。如果未提供 n,则返回值是函数中执行的最后一个命令退出状态

Therefore, we don't have to EVER use 0 and 1 to indicate True and False. The fact that they do so is essentially trivial knowledge useful only for debugging code, interview questions, and blowing the minds of newbies.

因此,我们不必使用 0 和 1 来表示 True 和 False。他们这样做的事实本质上是一些琐碎的知识,仅用于调试代码、面试问题和让新手大吃一惊。

The bash manual also says

bash 手册还说

otherwise the function's return status is the exit status of the last command executed

否则函数的返回状态是最后执行的命令退出状态

The bash manual also says

bash 手册还说

($?) Expands to the exit status of the most recently executed foreground pipeline.

( $?) 扩展到最近执行的前台管道退出状态

Whoa, wait. Pipeline? Let's turn to the bash manualone more time.

哇,等等。管道?让我们再看一次bash 手册

A pipeline is a sequence of one or more commandsseparated by one of the control operators ‘|' or ‘|&'.

管道是由一个控制运算符“|”分隔的一个或多个命令的序列 或“|&”。

Yes. They said 1 command is a pipeline. Therefore, all 3 of those quotes are saying the same thing.

是的。他们说 1 命令是一个管道。因此,所有这三个引文都在说同样的事情。

  • $?tells you what happened last.
  • It bubbles up.
  • $?告诉你最后发生了什么。
  • 它冒泡了。

My answer

我的答案

So, while @Kambus demonstratedthat with such a simple function, no returnis needed at all. I think was unrealistically simple compared to the needs of most people who will read this.

因此,虽然@Kambus 证明了使用如此简单的功能,但return根本不需要。与大多数阅读本文的人的需求相比,我认为这是不切实际的简单。

Why return?

为什么return

If a function is going to return its last command's exit status, why use returnat all? Because it causes a function to stop executing.

如果一个函数要返回其最后一个命令的退出状态,为什么要使用return呢?因为它会导致函数停止执行。

Stop execution under multiple conditions

在多个条件下停止执行

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

What we have here is...

我们这里有...

Line 04is an explicit[-ish] return true because the RHS of &&only gets executed if the LHS was true

Line04是一个显式 [-ish] 返回 true 因为&&只有在 LHS 为 true 时才会执行RHS

Line 09returns either true or false matching the status of line 08

Line09返回匹配 line 状态的 true 或 false08

Line 13returns false because of line 12

线13返回,因为线的错误12

(Yes, this can be golfed down, but the entire example is contrived.)

(是的,这可以打高尔夫球,但整个例子都是人为的。)

Another common pattern

另一种常见模式

# 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 statusvariable 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 exist 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 exitmight make you think it is exiting the script, when in reality it is exiting the $(...)subshell.

请注意设置status变量如何揭开$?. (当然你知道是什么$?意思,但比你知识渊博的人总有一天会不得不去谷歌它。除非你的代码在做高频交易,表现出一些爱,设置变量。)但真正的收获是“如果不存在状态”或相反的“如果退出状态”可以大声读出并解释它们的含义。然而,最后一个可能有点过于雄心勃勃,因为看到这个词exit可能会让你认为它正在退出脚本,而实际上它正在退出$(...)子 shell。



** If you absolutely insist on using return 1for false, I suggest you at least use return 255instead. This will cause your future self, or any other developer who must maintain your code to question "why is that 255?" Then they will at least be paying attention and have a better chance of avoiding a mistake.

** 如果你绝对坚持使用return 1for false,我建议你至少使用它return 255代替。这将导致您未来的自己或任何其他必须维护您的代码的开发人员质疑“为什么是 255?” 然后他们至少会注意并有更好的机会避免错误。

回答by Kambus

myfun(){
    [ -d "" ]
}
if myfun "path"; then
    echo yes
fi
# or
myfun "path" && echo yes

回答by RenRen

Be careful when checking directory only with option -d !
if variable $1 is empty the check will still be successfull. To be sure, check also that the variable is not empty.

仅使用选项 -d 检查目录时要小心!
如果变量 $1 为空,检查仍然会成功。当然,还要检查变量是否为空。

#! /bin/bash

is_directory(){

    if [[ -d  ]] && [[ -n  ]] ; then
        return 0
    else
        return 1
    fi

}


#Test
if is_directory  ; then
    echo "Directory exist"
else
    echo "Directory does not exist!" 
fi

回答by BuvinJ

I encountered a point (not explictly yet mentioned?) which I was stumbling over. That is, not how to returnthe boolean, but rather how to correctly evaluate it!

我遇到了一个问题(还没有明确提到?),这是我绊倒的。也就是说,不是如何返回布尔值,而是如何正确评估它!

I was trying to say if [ myfunc ]; then ..., but that's simply wrong. You must not use the brackets! if myfunc; then ...is the way to do it.

我想说if [ myfunc ]; then ...,但那完全是错误的。你不能使用括号!if myfunc; then ...是这样做的方法。

As at @Bruno and others reiterated, trueand falseare commands, not values! That's very important to understanding booleans in shell scripts.

截至@Bruno和其他重申,true并且false命令,不重视!这对于理解 shell 脚本中的布尔值非常重要。

In this post, I explained and demoed using boolean variables: https://stackoverflow.com/a/55174008/3220983. I strongly suggest checking that out, because it's so closely related.

在这篇文章中,我使用布尔变量进行了解释和演示:https: //stackoverflow.com/a/55174008/3220983。我强烈建议检查一下,因为它是如此密切相关。

Here, I'll provide some examples of returning and evaluatingbooleans from functions:

在这里,我将提供一些从函数返回和评估布尔值的示例:

This:

这个:

test(){ false; }                                               
if test; then echo "it is"; fi                                 

Produces no echo output. (i.e. falsereturnsfalse)

不产生回声输出。(即false返回假)

test(){ true; }                                                
if test; then echo "it is"; fi                                 

Produces:

产生:

it is                                                        

(i.e. truereturnstrue)

(即true返回真)

And

test(){ x=1; }                                                
if test; then echo "it is"; fi                                 

Produces:

产生:

it is                                                                           

Because 0 (i.e. true) was returned implicitly.

因为 0(即 true)是隐式返回的。

Now, this is what was screwing me up...

现在,这就是让我搞砸的事情......

test(){ true; }                                                
if [ test ]; then echo "it is"; fi                             

Produces:

产生:

it is                                                                           

AND

test(){ false; }                                                
if [ test ]; then echo "it is"; fi                             

ALSO produces:

还生产:

it is                                                                           

Using the brackets here produced a false positive! (I infer the "outer" command result is 0.)

在这里使用括号会产生误报!(我推断“外部”命令结果为 0。)

The major take away from my post is: don't use brackets to evaluate a boolean function (or variable) like you would for a typical equality check e.g. if [ x -eq 1 ]; then...!

我的帖子的主要内容是:不要像典型的相等性检查一样使用括号来评估布尔函数(或变量),例如if [ x -eq 1 ]; then...

回答by mrteatime

Use the trueor falsecommands immediately before your return, then returnwith no parameters. The returnwill automatically use the value of your last command.

在您的 之前使用trueorfalse命令return,然后return不带参数。该return会自动使用你的最后一个命令的值。

Providing arguments to returnis inconsistent, type specific and prone to error if you are not using 1 or 0. And as previous comments have stated, using 1 or 0 here is not the right way to approach this function.

return如果您不使用 1 或 0 ,则提供的参数不一致、类型特定且容易出错。正如之前的评论所述,此处使用 1 或 0 不是处理此函数的正确方法。

#!/bin/bash

function test_for_cat {
    if [  = "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

Output:

输出:

$ bash bash_return.sh

cat:
- True
hat:
- False

回答by Nephew

It might work if you rewrite this function myfun(){ ... return 0; else return 1; fi;}as this function myfun(){ ... return; else false; fi;}. That is if falseis the last instruction in the function you get false result for whole function but returninterrupts function with true result anyway. I believe it's true for my bash interpreter at least.

如果您将其重写function myfun(){ ... return 0; else return 1; fi;}为 this ,它可能会起作用 function myfun(){ ... return; else false; fi;}。也就是说,如果false是函数中的最后一条指令,您会得到整个函数的错误结果,但return无论如何都会以正确的结果中断函数。我相信至少对我的 bash 解释器来说是这样。

回答by Roy Shilkrot

I found the shortest form to test the function output is simply

我发现测试函数输出的最短形式很简单

do_something() {
    [[ -e  ]] # e.g. test file exists
}

do_something "myfile.txt" || { echo "File doesn't exist!"; exit 1; }

回答by Charlie

For code readability reasons I believe returning true/false should:

出于代码可读性的原因,我认为返回 true/false 应该:

  • be on one line
  • be one command
  • be easy to remember
  • mention the keyword returnfollowed by another keyword (trueor false)
  • 在一条线上
  • 成为一个命令
  • 容易记住
  • 提及关键字return后跟另一个关键字(truefalse

My solution is return $(true)or return $(false)as shown:

我的解决方案是return $(true)return $(false)如图所示:

is_directory()
{
    if [ -d "" ]; then
        return $(true)
    else
        return $(false)
    fi
}

回答by BuvinJ

Following up on @Bruno Bronosky and @mrteatime, I offer the suggestion that you just write your boolean return "backwards". This is what I mean:

跟进@Bruno Bronosky 和@mrteatime,我建议您只需“向后”编写布尔返回值。这就是我的意思:

foo()
{
    if [ "" == "bar" ]; then
        true; return
    else
        false; return
    fi;
}

That eliminates the ugly two line requirement for every return statement.

这消除了每个 return 语句的丑陋的两行要求。