Using a variable as a case condition in zsh

8,639

With this code saved to the file first,

pattern=fo*
input=foo
case $input in
$pattern)
   print T
   ;;
fo*)
   print NIL
   ;;
esac

under -x we may observe that the variable appears as a quoted value while the raw expression does not:

% zsh -x first
+first:1> pattern='fo*'
+first:2> input=foo
+first:3> case foo (fo\*)
+first:3> case foo (fo*)
+first:8> print NIL
NIL

That is, the variable is being treated as a literal string. If one spends enough time in zshexpn(1) one might be aware of the glob substitution flag

   ${~spec}
          Turn on the GLOB_SUBST option for the evaluation of spec; if the
          `~'  is  doubled,  turn  it  off.   When this option is set, the
          string resulting from the expansion will  be  interpreted  as  a
          pattern anywhere that is possible,

so if we modify $pattern to use that

pattern=fo*
input=foo
case $input in
$~pattern)                # !
   print T
   ;;
fo*)
   print NIL
   ;;
esac

we see instead

% zsh -x second
+second:1> pattern='fo*'
+second:2> input=foo
+second:3> case foo (fo*)
+second:5> print T
T

for your case the pattern must be quoted:

pattern='(foo|bar)'
input=foo
case $input in
$~pattern)
   print T
   ;;
*)
   print NIL
   ;;
esac
Share:
8,639

Related videos on Youtube

Smashgen
Author by

Smashgen

Updated on September 18, 2022

Comments

  • Smashgen
    Smashgen over 1 year

    My question is the zsh equivalent of the question asked here: How can I use a variable as a case condition? I would like to use a variable for the condition of a case statement in zsh. For example:

    input="foo"
    pattern="(foo|bar)"
    
    case $input in
    $pattern)
        echo "you sent foo or bar"
    ;;
    *)
        echo "foo or bar was not sent"
    ;;
    esac
    

    I would like to use the strings foo or bar and have the above code execute the pattern case condition.