[ "$((a||b^100))" -eq 1 ] && some commands
A shell's math expansion will handle the boolean &&
AND ||
OR and !
NOT conditions by evaluating the expression to either 1 for true or 0 for false. It will handle the bitwise &
AND |
OR and ^
XOR operators as well, but obviously those won't necessarily get you a 0 or 1, though a bitwise expression can serve as a field for a boolean eval, as it does here. Interestingly, the shell will even do the twiddle thing ~
and <<
left and >>
right SHIFTs.
And so if a
is true OR b^100
is true, the expansion evals to 1, matches the comparison -eq
[
test ]
and the shell continues to evaluate the rest of && some commands
.
It is usually easier to evaluate/compare integers in that way than to try to string together ...
...the -a
and -o
binary primaries and the (
and )
operators [which] have been marked obsolescent. (Many expressions using them are ambiguously defined by the grammar depending on the specific expressions being evaluated.)
(^direct quote from the test
spec)
Even when that works, 4 is as far as you can take it before you're in officially unspecified territory.
In the past, I've often found utility in applying a little abstraction like:
math(){ return "$((!($1)))"; }
...which can be used like...
math 'a||b^100' && some commands
Though that wasn't really my idea: I actually picked that up from the POSIX spec's XRAT Rationale section:
...[i]t was concluded that the test
command ([
) was sufficient for the majority of relational arithmetic tests, and that tests involving complicated relational expressions within the shell are rare, yet could still be accommodated by testing the value of "$(())"
itself. For example:
# a complicated relational expression
while [ "$(( (($x + $y)/($a * $b)) < ($foo*$bar) ))" -ne 0 ]
...or better yet, the rare script that has many complex relational expressions could define a function like this...
val() { return "$((!$1))"; }
(I added the "
quotes ^above, though. What's wrong with those guys?)
ksh
. By using[
and not[[
, you are invoking thetest
utility. The Posix and GNUtest
have nothing directly to do withksh
. – Otheus Jun 22 '15 at 08:22[
utility is built inksh
(on some systems,/bin/test
is even implemented as aksh
script).[[
doesn't invoke the test utility. There are subtle variations between every[
/test
implementations. Posix is a standard body. It doesn't provide with an implementation of[
, just a specification which various implementations (ksh/bash/Bourne/zsh/yash/ash... builtin, GNU test...) try to follow though they generally also support extensions. – Stéphane Chazelas Jun 22 '15 at 10:19