shellswitch-statement

Does the -?* pattern provide any advantage over -* for matching unknown command line option?


At http://mywiki.wooledge.org/BashFAQ/035 in the 'Manual loop' section, they have this code.

#!/bin/sh
# (POSIX shell syntax)

# Reset all variables that might be set
file=
verbose=0

while :; do
    case $1 in
        -h|-\?|--help)   # Call a "show_help" function to display a synopsis, then exit.
            show_help
            exit
            ;;
        -f|--file)       # Takes an option argument, ensuring it has been specified.
            if [ "$2" ]; then
                file=$2
                shift 2
                continue
            else
                echo 'ERROR: Must specify a non-empty "--file FILE" argument.' >&2
                exit 1
            fi
            ;;
        --file=?*)
            file=${1#*=} # Delete everything up to "=" and assign the remainder.
            ;;
        --file=)         # Handle the case of an empty --file=
            echo 'ERROR: Must specify a non-empty "--file FILE" argument.' >&2
            exit 1
            ;;
        -v|--verbose)
            verbose=$((verbose + 1)) # Each -v argument adds 1 to verbosity.
            ;;
        --)              # End of all options.
            shift
            break
            ;;
        -?*)
            printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
            ;;
        *)               # Default case: If no more options then break out of the loop.
            break
    esac

    shift
done

# Suppose --file is a required option. Check that it has been set.
if [ ! "$file" ]; then
    echo 'ERROR: option "--file FILE" not given. See --help.' >&2
    exit 1
fi

# Rest of the program here.
# If there are input files (for example) that follow the options, they
# will remain in the "$@" positional parameters.

I am trying to understand to understand these lines from the script.

    -?*)
        printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
        ;;

I have been using the pattern -* instead to match unknown option. But this script uses the pattern -?* required to match unknown?

Why advantages does the -?* pattern provide over the pattern -* for matching unknown options?


Solution

  • A solo dash is sometimes used to read from stdin, -?* won't catch that.

    The ? is the shell wildcard to match any single character. * matches zero or more characters. Thus -?* enforces that there is at least one character after the dash.