Search code examples
stringshboolean-operations

In 'sh' how to put the result of a string comparison into a variable?


In basic 'shell', how do I put the result of a string comparison into a boolean variable?

Consider:

isweekday() {
          w=$(date +%w)
          if [[ $w == "0" ]] || [[ $w == "6" ]]; then
                  false
          else
                  true
          fi

  }

One can debate whether it would be clearer or not, but is there a way to assign the result of the 'if' expression to a boolean variable, e.g.

isweekday() {
          w=$(date +%w)
          wd=<boolean result of [[ $w == "0" ]] || [[ $w == "6" ]]>
          return $wd
}

After some experimentation, I got closer to what I want but it still isn't what I'm after:

isweekday() {
  w=$(date +%w)
  [[ $w == "0" ]] || [[ $w == "6" ]] 
}

This works and does not require the conditional, but it looks wrong, however if you do:

if isweekday; then
  echo 'weekday'
fi

you will get the right result. This seems to be because the exit code of 'true' is 0 and the exit code of 'false' is 1 (not quite sure why that is...)


Solution

  • There are no boolean variables. All shell variables are strings (though there are limited facilities for interpreting them as integer numbers for basic comparisons etc and basic arithmetic).

    The exit code 0 is reserved for success; all other exit codes (up to the maximum 255) signify an error (though some nonstandard tools use this facility to communicate non-error results by way of convention; the caller is then assumed to understand and agree on this ad-hoc use of the exit code).

    Perhaps then the simplest answer to what you appear to be asking is to save the exit code. It is exposed in the variable $?. But very often, you should not need to explicitly examine its value; indeed, your final isweekday code looks by far the most idiomatic and natural, and returns this code from [[ implicitly.

    I don't understand why you think your final code "looks wrong"; this is precisely how you would use a function in a conditional.

    However, in some sense, a case statement would look less cluttered here (but this syntax is somewhat jarring at first for other reasons, until you get used to it).

    is_weekday () {
        case $(date +%w) in
          0 | 6) return 1;;
        esac
        return 0
    }
    

    This is portable to POSIX sh, unlike the Bash-only [[...]] syntax you were using. Perhaps see also Difference between sh and bash