Search code examples
bashescapingcaseglob

What is the correct way to check for a '?' in a case statement


I have below bash script using getopts. My code works as expected, i.e.,when an invalid option is specified, $myopt variable is set to '?' character and the case statement currectly processes the code matching the '?'.
Else where I see similar code using '\?' instead of just '?' in the case statement (please see the last three commented lines of the code block).

Is there any specific reason why the'?' is escaped ? I am aware any charcter can be escaped using '\' but my code works perfectly fine without escaping the '?'.

#!/bin/bash
while getopts ":abc" myopt; do
    case $myopt in
      [a-c])
       echo "$myopt is a valid option!" >&2
       ;;
      ?)
       echo "$OPTARG is an invalid option!" >&2
       ;;
     # \?)
     #  echo "$OPTARG is an invalid option!" >&2
     #  ;;
     esac
done

For the benefit of other reading this, below code will only work if '?' is escaped (see the accepted answer for a good explanation).

#!/bin/bash 
while getopts ":abc" myopt; do
    case $myopt in
      \?)
       echo "$OPTARG is an invalid option!" >&2
       ;;

   [a-c])
       echo "$myopt is a valid option!" >&2
       ;;
    esac
done

if the script file is myscript.sh it can be tested like this -

./myscript.sh -a -z -a  

Solution

  • For the Bash case statement the ? is a wildcard matching any single character/digit. If you escape it with \? it specifically is trying to match the '?' char.

    The case will continue to find a match, so in this case if the variable isn't [a-c] (a, b or c) then it will match if it the variable is 1 char.