Reputation: 20329
I'm trying to write a Bash script that uses a variable as a pattern in a case statement. However, I just cannot get it to work.
Case statement:
case "$1" in
$test)
echo "matched"
;;
*)
echo "didn't match"
;;
esac
I've tried this with assigning $test
as aaa|bbb|ccc
, (aaa|bbb|ccc)
, [aaa,bbb,ccc]
and several other combinations. I also tried these as the pattern in the case statement: @($test)
, @($(echo $test))
, $($test)
. Also no success.
For clarity, I would like the variable to represent multiple patterns like this:
case "$1" in
aaa|bbb|ccc)
echo "matched"
;;
*)
echo "didn't match"
;;
esac
Upvotes: 27
Views: 18733
Reputation: 241808
You can use the extglob
option:
#! /bin/bash
shopt -s extglob # enables pattern lists like @(...|...)
test='@(aaa|bbb|ccc)'
for x in aaa bbb ccc ddd ; do
echo -n "$x "
case "$x" in
$test) echo Matches.
;;
*) echo Does not match.
esac
done
Upvotes: 27
Reputation: 29
Using eval also works:
eval 'case "$1" in
'$test')
echo "matched"
;;
*)
echo "did not match"
;;
esac'
Upvotes: 2
Reputation: 47269
Here's something a bit different:
#!/bin/bash
pattern1="aaa bbb ccc"
pattern2="hello world"
test=$(echo -e "$pattern1\n$pattern2" | grep -e $1)
case "$test" in
"$pattern1")
echo "matched - pattern1"
;;
"$pattern2")
echo "matched - pattern2"
;;
*)
echo "didn't match"
;;
esac
This makes use of grep
to do the pattern matching for you, but still allows you to specify multiple pattern sets to be used in a case-statement structure.
For instance:
aaa
, bbb
, or ccc
is the first argument to the script, this will output matched - pattern1
.hello
or world
is the first argument, this will output matched - pattern2
.didn't match
.Upvotes: 3