The bash manual states:
case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
Each pattern examined is expanded using tilde expansion, parameter and variable expansion, arithmetic substitution, command substitution, and process substitution.
No «Pathname expansion»
Thus: a pattern is NOT expanded with «Pathname expansion».
Therefore: a pattern could NOT contain "|" inside. Only: two patterns could be joined with the "|".
This works:
s1="foo"; s2="bar" # or even s1="*foo*"; s2="*bar*"
read choice
case $choice in
$s1|$s2 ) echo "Two val choice $choice"; ;; # not "$s1"|"$s2"
* ) echo "A Bad choice! $choice"; ;;
esac
Using « Extended Globbing »
However, word
is matched with pattern
using « Pathname Expansion » rules.
And « Extended Globbing » here, here and, here allows the use of alternating ("|") patterns.
This also work:
shopt -s extglob
string='@(foo|bar)'
read choice
case $choice in
$string ) printf 'String choice %-20s' "$choice"; ;;&
$s1|$s2 ) printf 'Two val choice %-20s' "$choice"; ;;
*) printf 'A Bad choice! %-20s' "$choice"; ;;
esac
echo
String content
The next test script shows that the pattern that match all lines that contain either foo
or bar
anywhere is '*$(foo|bar)*'
or the two variables $s1=*foo*
and $s2=*bar*
Testing script:
shopt -s extglob # comment out this line to test unset extglob.
shopt -p extglob
s1="*foo*"; s2="*bar*"
string="*foo*"
string="*foo*|*bar*"
string='@(*foo*|*bar)'
string='*@(foo|bar)*'
printf "%s\n" "$string"
while IFS= read -r choice; do
case $choice in
"$s1"|"$s2" ) printf 'A first choice %-20s' "$choice"; ;;&
$string ) printf 'String choice %-20s' "$choice"; ;;&
$s1|$s2 ) printf 'Two val choice %-20s' "$choice"; ;;
*) printf 'A Bad choice! %-20s' "$choice"; ;;
esac
echo
done <<-\_several_strings_
f
b
foo
bar
*foo*
*foo*|*bar*
\"foo\"
"foo"
afooline
onebarvalue
now foo with spaces
_several_strings_
eval
, escaping $choice, the parens, asterisk, semicolons, and newlines. Ugly, but it "works". – Jeff Schaller Oct 07 '15 at 18:50read
bit stopped me. in my opinion user input validation, which is what this appears to be,case
patterns should not be at the top of the evaluation list, and should rather be pruned down to the*
default pattern such that the only results that reach there are guaranteed acceptable. still, because the issue is parse/expansion order, then a second evaluation could be what's called for. – mikeserv Oct 08 '15 at 00:57dmenu
. – Vorac Jun 29 '20 at 03:41