Search code examples
shposix

posix disallows alternation in case. is this a typo?


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.


Solution

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