I want to define a set of values for a single variable. E.g.
singleDigit={0,1,2,3,4,5,6,7,8,9}
If the user gives 10 it should exit with an error.
How can this be achieved without using a loop, but an array instead?
I want to define a set of values for a single variable. E.g.
singleDigit={0,1,2,3,4,5,6,7,8,9}
If the user gives 10 it should exit with an error.
How can this be achieved without using a loop, but an array instead?
If you want to store several values into a variable, that's where you'd use an array like:
allowed_values=(0 1 2 3 4 5 6 7 8 9)
Or
allowed_values=({0..9})
with bash3+
(syntax borrowed from zsh
now also available in ksh93
).
And if you want to check whether a given string is among any of those values, you could define a function like:
isin() {
local s
for s in "${@:2}"; do
[[ $1 = "$s" ]] && return 0
done
return 1
}
if isin "$input" "${allowed_values[@]}"
(in zsh
, you can do if ((allowed_values[(eI)$input]))
).
Note that the comparison is lexical (as in 01 != 1). Do do numerical comparison, you'd use [ "$1" -eq "$s" ] 2> /dev/null
(note that 010
is 10
, not 8
). Do not use [[ $1 -eq $s ]]
or ((s == $1))
as those introduce arbitrary command injection vulnerabilities.
If you want to assign a pattern to a variable to match against some input, you'd use a scalar variable and use one of the 2 (3 with the extglob
option) pattern syntaxes supported by bash
:
wildcard/glob pattern
pattern='[0-9]'
Used as:
case $input in
($pattern) echo OK;;
(*) echo NOK
esac
or
if [[ $input = $pattern ]]; then
echo OK
else
echo NOK
fi
Extended Regular Expression:
regex='^[0-9]$'
used as:
if [[ $input =~ $regex ]]; then
echo OK
else
echo NOK
fi
In the general case, for values other than single-character ones, you'd use:
regex='^(one|two|three)$'
And for patterns, you'd need the extglob
option:
shopt -s extglob
pattern='@(one|two|three)'
Another approach with bash4+
, or ksh93
or zsh
is to use an associative array:
With bash
, ksh93
:
typeset -A allowed_values
allowed_values=([one]=1 [two]=1 [three]=1)
if ((allowed_values[$input])); then
echo OK
else
echo NOK
fi
In zsh
, same but the assignment syntax is:
typeset -A allowed_values
allowed_values=(one 1 two 1 three 1)
(note that with bash
, you can't have the empty string as an allowed value).
{x..y}
was added in bash 3 (2004),
– Stéphane Chazelas
Jul 20 '16 at 11:17
If only the numbers 0 through 9 are allowable as input, all you need is a simple IF statement.
#!/bin/bash
echo -n Please enter a single digit:
read single_digit
if [ $single_digit -lt 10 ]; then
echo Thanks for $single_digit
else
echo Screwball!!! I said SINGLE DIGIT!!
fi