POSIX states:
The format for the case construct is as follows:
case word in [(] pattern1 ) compound-list ;; [[(] pattern[ | pattern] ... ) compound-list ;;] ... [[(] pattern[ | pattern] ... ) compound-list] esac
This appears to disallow alternation (ie. multiple patterns) with the first compound-list.
Clearly, this is not how implementations behave.
$ for cmd in bash dash 'busybox sh' ksh; do
> $cmd -c 'case a in a|b|c) echo ok ;; *) echo no ; esac'
> done
ok
ok
ok
ok
$
Nor how the grammar itself defines it further down on that page:
case_clause : Case WORD linebreak in linebreak case_list Esac | Case WORD linebreak in linebreak case_list_ns Esac | Case WORD linebreak in linebreak Esac ; case_list_ns : case_list case_item_ns | case_item_ns ; case_list : case_list case_item | case_item ; case_item_ns : pattern ')' linebreak | pattern ')' compound_list | '(' pattern ')' linebreak | '(' pattern ')' compound_list ; case_item : pattern ')' linebreak DSEMI linebreak | pattern ')' compound_list DSEMI linebreak | '(' pattern ')' linebreak DSEMI linebreak | '(' pattern ')' compound_list DSEMI linebreak ; pattern : WORD /* Apply rule 4 */ | pattern '|' WORD /* Do not apply rule 4 */ ;
Is this a bug in the spec? (In particular the 1
in pattern1
looks suspiciously like a mistyped ]
- as if part of that line had been lost/corrupted.)
The same definition text appears as far back as the 2004 edition.
Yes, it's a bug. That line was removed from the standard as a result of this bug report filed back in 2021. The issue 8 drafts have the following text instead:
The format for the case construct is as follows:
case word in [[(] pattern[ | pattern] ... ) compound-list terminator] ... [[(] pattern[ | pattern] ... ) compound-list] esac
Where terminator is either ";;" or ";&" and is optional for the last compound-list.