O manual do bash declara:
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.
Não «Expansão do nome do caminho»
Assim: um padrão NÃO é expandido com "Expansão do nome do caminho".
Portanto: um padrão NÃO pode conter "|" dentro. Apenas: dois padrões podem ser associados ao "|".
Isso funciona:
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
Usando o «alargamento da globalização»
No entanto, word
é correspondido com pattern
usando as regras de "Expansão de nome de caminho".
E "Ampliação do Globo" aqui , aqui e, aqui permite o uso de padrões alternativos ("|").
Isso também funciona:
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
Conteúdo da sequência
O próximo script de teste mostra que o padrão que corresponde a todas as linhas que contêm foo
ou bar
em qualquer lugar é '*$(foo|bar)*'
ou as duas variáveis $s1=*foo*
e $s2=*bar*
Script de teste:
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_