In my bash script, I am checking that the first argument is either -
, 0
, or +
, using following if
statement:
LEVEL=$1
if [ "$LEVEL" -ne "-" ] && [ "$LEVEL" -ne "0" ] && [ "$LEVEL" -ne "+" ]
then
echo "The value of LEVEL must be either -, 0, or +!"
exit 1
fi
But it's giving me the error [: -: integer expression expected
, referring to the line with the if
statement conditions.
I've been trying lots of different syntaxes (eg, double vs single brackets, quoting vs non-quoting the variables and string literals), but I can't figure it out.
The conventional approach, compatible with POSIX sh rather than leveraging bashisms, is to use the case
statement:
case $level in
-|0|+)
echo "Got it!" ;;
*)
echo "Not a valid value" ;;
esac
That said, if you wanted to use test
, you could do that too:
if [ "$LEVEL" != "-" ] && [ "$LEVEL" != "0" ] && [ "$LEVEL" != "+" ]; then
...
fi
!=
is the negating string comparison operator, and =
(not ==
) is the POSIX-compatible positive-matching one. (Bash extends POSIX to support ==
in test, but making a habit of using this extension will get you into trouble if you try to write code for a pure POSIX shell later).
In a comment, a follow-up question was asked, in terms of whether the set of possible characters could be read from a variable. In general, yes, though there are some caveats:
# no spaces in possible_levels, as we're using it to form a pattern
possible_levels='-0+'
possible_levels_pattern="[${possible_levels}]"
if [[ $value = $possible_levels_pattern ]]; then
echo "value contains a valid level"
fi
...As an even shorter approach that allows your input string to be used unmodified, and is almost correct:
# caveat: will say some incorrect strings, like "- 0" or "0 +", are valid levels
possible_levels=' - 0 +'
check_level() {
[[ " $possible_levels " = *" $1 "* ]] && echo "Value is a valid level"
}
...or, as yet another implementation (verbose, but correct in the particulars):
possible_levels=' - 0 +'
read -a possible_levels_array <<<"$possible_levels"
check_level() {
local possible_level
local value=$1
for possible_level in "${possible_levels_array[@]}"; do
[[ $value = "$possible_level" ]] && return 0
done
return 1
}
if check_level "$value"; then
echo "$value is a valid level"
else
echo "$value is not a valid level"
fi
Obviously, this is a lot of work, and in general, just hardcoding the comparisons when appropriate (and possible without a loss of safety) will save you trouble over trying to make things more generic than they truly need to be.
Now, if we could pass in the variable as an associative array, without needing to support the silly space-separated-list thing, that makes it much shorter:
declare -A possible_levels=( [-]=1 [+]=1 [0]=1 )
if [[ ${possible_levels[$value]} ]]; then
echo "valid level"
else
echo "invalid level"
fi
You can use [[ and ]]
use a selector:
if [[ "$LEVEL" == [0+-] ]]; then
echo "got it"
fi
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.