I want to check if [[ $var == foo || $var == bar || $var == more ]] without repeating $var n times.
The portable solution uses case:
# Bourne
case $var in
foo|bar|more) ... ;;
esacIn Bash and ksh, Extended globs can also do this within a [[ command:
# bash/ksh
if [[ $var == @(foo|bar|more) ]]; then
...
fiAlternatively, you may loop over a list of patterns, checking each individually.
# bash/ksh93
[[ -v BASH_VERSION ]] && shopt -s extglob
# usage: pmatch string pattern [ pattern ... ]
function any {
[[ -n $1 ]] || return
typeset pat match=$1
shift
for pat; do
[[ $match == $pat ]] && return
done
return 1
}
var='foo bar'
if any "$var" '@(bar|baz)' foo\* blarg; then
echo 'var matched at least one of the patterns!'
fiFor logical conjunction (return true if $var matches all patterns), ksh93 can use the & pattern delimiter.
# ksh93 only
[[ $var == @(foo&bar&more) ]] && ...For shells that support only the ksh88 subset (extglob patterns), you may DeMorganify the logic using the negation sub-pattern operator.
# bash/ksh88/etc...
[[ $var == !(!(foo)|!(bar)|!(more)) ]] && ...But this is quite unclear and not much shorter than just writing out separate expressions for each pattern.