Note that bash's ;;& (added in 4.0 in 2009) is the equivalent of zsh's ;| (from 2007; also in mksh since 2011), it's not a fall through in the sense of C's fallthrough when you omit the break in a switch statement in that the next pattern will still be checked.
As in bash's
case a in
(a) echo a;;&
(b) echo b
esac
Or zsh's / mksh's
case a in
(a) echo a;|
(b) echo b
esac
Won't output both a and b like a
switch('a') {
case 'a': puts("a"); /* fall through */
case 'b': puts("b");
}
would in C.
For that, you'd need ;& instead (itself from ksh93 and found in all of bash, zsh and mksh; while ;; and the whole case...esac structure is from the Bourne shell from the late 70s).
Also, in bash's
case $string in
(a*) echo starts with a;;&
(*b) echo ends with b;;
(*c*) echo neither starts with a nor ends in b but contains c
esac
That is if you mix ;;& and ;;, then you can't just do pattern matching in sequence independently as a standard equivalent.
In that example, the *c* case will only be reached if the string matches neither a* not *b.
One approach can be to do all 3 checks and then consider all combinations:
test1=0 test2=0 test3=0
case $string in
(a*) test1=1
esac
case $string in
(*b) test2=1
esac
case $string in
(*c*) test3=1
esac
case $test1$test2$test3 in
(11?) echo starts with a
echo ends in b;;
(10?) echo start with a;;
(01?) echo ends in b;;
(??1) echo neither starts with a nor ends in b but contains c
esac
Or adapt on a case by case basis, using a combination of case and if and/or &&/||, like here:
flag=false
case $string in
(a*) echo starts with a
flag=true
esac
case $string in
(*b) echo ends in b
flag=true
esac
"$flag" ||
case $string in
(*c*) echo neither starts with a nor ends in b but contains c
esac
Or do it all with if/then/else, using flags or repeating the checks like in:
match() case $1 in ($2) true;; (*) false; esac
if match "$string" 'a*'; then
echo starts with a
fi
if match "$string" '*b'; then
echo ends in a
fi
if
! match "$string" 'a*' &&
! match "$string" '*b' &&
match "$string" '*c*'
then
echo neither starts with a nor ends in b but contains c
fi
Which may make it easier to follow.
With the use-case you've now added:
case $5 in
(C | C++)
export CXXFLAGS="${CXXFLAGS} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
esac
case $5 in
(C) export CFLAGS="${CFLAGS} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}";;
(C++) ;;
(*) export FLAGS_USER="${FLAGS_USER} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
esac
Or:
c_or_cxx=false
case $5 in
(C) export CFLAGS="${CFLAGS} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
c_or_cxx=true;;
(C++) c_or_cxx=true;;
(*) export FLAGS_USER="${FLAGS_USER} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
esac
if "$c_or_cxx"; then
export CXXFLAGS="${CXXFLAGS} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
fi
You can also include the common code in a function or variable to eval (variable may be preferable here as the code includes references to $1):
for_c_and_cxx='
export CXXFLAGS="${CXXFLAGS} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
'
case $5 in
(C)
export CFLAGS="${CFLAGS} ${1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
eval "$for_c_and_cxx";;
(C++)
eval "$for_c_and_cxx";;
(*)
export FLAGS_USER="${FLAGS_USER} {1}${SUSUWU_DEPENDENCY_INCLUDE_PATH}"
esac
Note that it's only the Bourne shell that required you omitted the opening (s (the Bourne shell also did not support export var=value and in any case was not a POSIX compliant shell). In modern/standard sh implementations, you can include it which IMO makes for more readable code and lets you use your editors ability to check for matching parenthesis for instance.
/bin/shdoesn't identify a particular shell. On some systems it points to bash (in a POSIX-compliant mode); on others it may be dash or even the original Bourne shell. All you know is that it's POSIX-compliant; you can't tell what extra features it may support. (Even in POSIX mode, bash supports lots of things that other shells don't. — Which means that running on/bin/shdoesn't prove that your script is POSIX-compliant… Dash is much more suited to that.)