Home > Software engineering >  complicated bash functions returning boolean
complicated bash functions returning boolean

Time:10-08

I want to do something like this:

function one {
    if [ "$1" == "hello" ]; then
        return true
    fi
    return false
}

if [ one hello -o one goodbye ]; then
    echo "Well, that's weird."
fi

As written, I know this doesn't work. Bash won't let you return boolean values. You can return 0 or 1. But bash doesn't seem to like using 0 or 1 as boolean expressions. So instead I have to return 0 instead of true and 1 for false. I can live with that. But then my if becomes:

if [ one hello -eq 0 -o one goodbye -eq 0 ] ...

Which I can do, but it's awkward. But THAT doesn't work, either, because test doesn't want to call my function with an argument.

if [ `one hello` -eq 0 -o `one goodbye` -eq 0 ] ...

Finally, I think that version works. But it's fugly.

Is there an elegant way to:

  • Have a bash function that returns true/false
  • And it takes arguments
  • And then it gets used in a complex if-statement (there's some combination of -o / -a between the [] )

I'd really like to have some way of writing:

if [ myfunc1 $somearg -a $myfunc2 $someotherarg ]; then ...

For now, I'm doing it the fugly way.

CodePudding user response:

You don't really write predicates like this. Instead, you set the exit status to 0 if a function succeeds, or non-zero value if it fails. The if statement then checks the exit status directly.

one () {
    if [ "$1" = "hello" ]; then
        return 0
    fi
    return 1
}

if one hello || one goodbye; then
    echo "Well, that's weird."
fi

Since [ itself is a command that has a 0 exit status when the test is true and 1 if false, you can define one as simply

one () {
    [ "$1" = "hello" ]
}

If no return statement is encountered, the exit status of a function is the exit status of the last command to execute.

CodePudding user response:

Functions don't return true or false. Instead, they succeed or fail. if checks to see if a command succeeded or not. [ is a very common command that is used in shell scripts, but it misleads many into believing it is part of the grammar. It is not. You can simply write:

if one hello || one goodbye; then
    echo "Well, that's weird."
fi

You don't want to use -a or -o. (Those are typically passed as arguments to [, but are effectively deprecated in that usage.) Instead, use the shell operators && and ||.

CodePudding user response:

The fun thing about the strings "true" and "false" is that they are also shell builtin commands that have the expected exit status:

function one {
    [[ "$1" == "hello" ]] && echo true || echo false
}

a=$(one hello)
b=$(one goodbye)
if $a || $b; then ...

But, don't do this. Keep it simple as other answers advice.

CodePudding user response:

Like this?

one () {
    if [ "$1" = "hello" ]; then
        echo true; return 0
    fi
    echo false; return 1
}

$ one hello && one bye || one hello
true
false
true
  •  Tags:  
  • bash
  • Related