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.)