Search code examples
bashshellposixdash-shell

Why does field splitting of WORD not occur in `case WORD in` statement when WORD is a variable?


Shell script:

#!/bin/sh
a="foo  bar"

case $a in
    "foo  bar")
        echo case 1
        ;;
esac

case foo  bar in
    "foo  bar")
        echo case 2
        ;;
esac

Executing this with bash leads to the following output and error.

case 1
foo: line 10: syntax error near unexpected token `bar'
foo: line 10: `case foo  bar in'

Executing this with dash:

case 1
foo: 10: foo: Syntax error: word unexpected (expecting "in")` leads to the following output and error.

I don't understand why the first case statement succeeds but the second one does not.

As per the POSIX document at http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05, field splitting would occur in either case, so after $a is expanded to foo bar in the first case statement, it should be equivalent to the second one.

So both should fail. Why does the first case statement succeed?


Solution

  • Word splitting is not done in the first case for the word used in case statement. From POSIX:

    Case Conditional Construct

    The conditional construct case shall execute the compound-list corresponding to the first one of several patterns (see Pattern Matching Notation) that is matched by the string resulting from the tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal of the given word.

    So whether you quote the word or not, it's not going to be expanded and is safe without quotes.

    case $a in  
       ...
    esac
    

    and

    case "$a" in    
       ...
    esac
    

    are going to work as expected.

    Clearly, this is not equivalent to the second example where you have two words in the case statement.