How to build a conditional assignment in bash?
I'm looking a way to build conditional assignments in bash:
开发者_运维问答In Java it looks like this:
int variable= (condition) ? 1 : 0;
If you want a way to define defaults in a shell script, use code like this:
: ${VAR:="default"}
Yes, the line begins with ':'. I use this in shell scripts so I can override variables in ENV, or use the default.
This is related because this is my most common use case for that kind of logic. ;]
As per Jonathan's comment:
variable=$(( 1 == 1 ? 1 : 0 ))
EDIT:
I revised the original answer which just echo
'd the value of the condition operator, it didn't actually show any assignment.
myvar="default" && [[ <some_condition_is_true> ]] && myvar="non-default"
real examples:
DELIM="" && [[ "$APP_ENV_RESOLVED" != "" ]] && DELIM=$INNER_DELIM
The condition can be "(( ... ))" as well:
filepath=/proc/drbd && (( $# > 0 )) && filepath=$1
In addition to the other more general answers (particularly as per Jonathan's comment and Kevin's more general answer [which also supports strings]) I'd like to add the following two solutions:
setting the variable to either 0
or 1
based on the condition:
(as the question's example suggests.)
The general form would read
(condition); variable=$?;
where $variable
results in being either 0
or 1
and condition
can be any valid conditional expression.
E.g. checking a variable ...
[[ $variableToCheck == "$othervariable, string or number to match" ]]
variable=$?
... or checking a file's existence ...
[ -f "$filepath" ]
fileExists=$?
... or checking the nummerical value of $myNumber
:
(( myNumber >= 1000000000 ))
is_huge_number=$?
The advantages of this solution is that
- it supports arbitrary conditional expressions, including strings
(which are not supported in arithmetic expressions of Jonathan's solution) - that
variable
gets declared in any case, unlike in griffon's answer:[ -z "$variable" ] && variable="defaultValue"
Which would matter in case you want to nameref it later on (e.g. from within a function).
Please note: In Bash, the special variable $?
always contains the exit code of the previously executed statement (or statement block; see the man bash for more details). As such, a positive result is generally represented by the value 0
, not 1
(See my comment below, thanks Assimilater for pointing it out). Thus, if the condition is true (e.g [[2 eq 2]]
) then $?=0
.
If instead you need 0 or 1 in your variable (e.g. to print or do mathematical calculations) then you need to employ boolean negation using a leading exclamation mark (as pointed out by GypsySpellweaver in the comments below): ( ! condition ); variable=$?
or ! ( condition ); variable=$?
. (However, readability in terms of what happens might be a bit less obvious.)
Another possible solution by Jonathan would be variable=$(( 1 == 1 ? 1 : 0 ))
- which, however, is creating a subshell.
If you want to avoid the creation of a subshel, keep good readability or have arbitrary conditions, use one of the following solutions.
setting the variable to arbitrary values:
as it is done in most other answers, it could adapted as follows:
(condition) \
&& variable=true \
|| variable=false
e.g as in
[[ $variableToCheck == "$othervariable, string or number to match" ]] \
&& variable="$valueIfTrue" \
|| variable="$valueIfFalse"
or to get 1 in a positive check, and 0 upon failure (like in the question's example):
[[ $variableToCheck == "$othervariable, string or number to match" ]] \
&& variable=1 \
|| variable=0
(for the last example, - as already mentioned in the notes above - the same can be achieved with boolean negation using a leading exclamation mark:
[[ ! $variableToCheck == "$othervariable, string or number to match" ]]
variable=$?
The advantages of this solution is that
- it might be considered a bit better readable than Kevin's answer
myvar="default" && [[ <some_condition_is_true> ]] && myvar="non-default"
, and - the
$valueIfTrue
is conditionally evaluated only if needed,
which would matter in case you'd do something- with side-effect, like
variable=$((i++))
, or{ variable=$1; shift; }
- high computation, like
variable=$(find / -type f -name ListOfFilesWithThisNameOnMySystem)
- with side-effect, like
- is a bit shorter than ghostdog74's answer
(which, however is great if you have multiple conditions!) - does not open a subshell as in Pierre's answer
- and as above:
- it supports arbitrary conditional expressions, including strings
(which are not supported in arithmetic expressions of Jonathan's solution) - that
variable
gets declared in any case, unlike in griffon's answer:[ -z "$variable" ] && variable="defaultValue"
Which would matter in case you want to nameref it later on (e.g. from within a function).
- it supports arbitrary conditional expressions, including strings
I wanted to do a conditional assignment with strings and I ended up with:
VAR=$([ "$MYVALUE" = "value" ] && echo "YES" || echo "NO")
Which is:
VAR=$([ condition ] && value_when_true || value_when_false)
Big ups to @Demosthenex and especially @Dennis Williamson for the shortest and easiest solution I've seen. Leave it to bash to require a bunch of parentheses for a simple ternary assignment. Ahh, the 60s! And to put it all together in an example...
echo $BASHRULES; # not defined
# no output
: ${BASHRULES:="SCHOOL"} # assign the variable
echo $BASHRULES # check it
SCHOOL # correct answer
: ${BASHRULES="FOREVER?"} # notice the slightly different syntax for the conditional assignment
echo $BASHRULES # let's see what happened!
SCHOOL # unchanged! (it was already defined)
I wrote that a long time ago.. these days I'd probably get more excited over a solution like...
PLATFORM=iphonesimulator
OTHERSDK=iphone && [[ $PLATFORM=~os ]] \
&& OTHERSDK+=simulator \
|| OTHERSDK+=os
$OTHERSDK
⇥iphoneos
If you want to assign a value unless variable is empty use this:
[ -z "$variable" ] && variable="defaultValue"
You can put as well, each other condition on the []
another way using a case/switch
case "$variable" in
condition) result=1 ;;
*) result=0 ;;
esac
精彩评论