79433327

Date: 2025-02-12 14:03:38
Score: 1
Natty:
Report link

An addition to @Denis' answer: If you only going to use your scripts in a modern Linux environment, you might consider using getopt instead of getopts; as Linux's getopt has additional support for --long-flags!

Here's a working proof of concept modified from this Wikipedia article:

#!bin/bash


# Formating
bold=$(tput bold)
normal=$(tput sgr0)

function test_arg_parse(){
    flag_set=0
    flag_with_arg=""
    opt_flag=""

    # Exit if arg parsing fails
    args=$(getopt --options 'fF:O::' \
                  --longoptions 'flag,flagWithArg:,argument:,optionalFlag::' \
                  -- "${@}") || exit

    eval "set -- ${args}"

    while true; do
        case "${1}" in
            (-f | --flag)
                ((flag_set++))
                shift
            ;;
            (-F | --flagWithArg | --argument)
                flag_with_arg=${2}
                shift 2
            ;;
            (-O | --optionalFlag)
                # handle optional: getopt normalizes it (the argument)
                # into an empty string
                if [[ -n ${2} ]] ; then
                    opt_flag=${2}
                    echo "optional flag is present!"
                fi
                shift 2
            ;;
            (--)
                shift
                break
            ;;
            (*)
                exit 1    # error
            ;;
        esac
    done

    remaining_args=("${@}")

    echo "args are: \"${args[@]}\""
    cat <<EOF
===args===
flag_set is       "$bold$flag_set$normal"
flag_with_arg is  "$bold$flag_with_arg$normal"
opt_flag is       "$bold$opt_flag$normal"
===~~~~===
remaining_args is "$bold${remaining_args[@]}$normal"

EOF
}

### Usages: ###
echo "Test with: $bold--flag -F\"Hello\"$normal"

test_arg_parse --flag -F"Hello"


echo "Test with: $bold--flagWithArg=\"Hola\" -O\"Bird is a Fake\" some_extra_args$normal"

test_arg_parse --flagWithArg="Hola" -O"Bird is a Fake" some_extra_args


echo 'You can chain some of the short options together (but why tho?)$normal'
echo "Test with: $bold-fF\"Hello!\" -O\"Bird is a Fake\" some_extra_args"

test_arg_parse -fF"Hello!" --optionalFlag="Bird is a Fake" some_extra_args


echo -e "\n**NOTE: short flags and their argument must mot be separated by any white space:"
echo "Test with: $bold--flagWithArg \"This is fine\" -O \"This is not :(\"$normal"

test_arg_parse --flagWithArg "This is fine" -O "This is not :("

Output:


    Test with: --flag -F"Hello"
    args are: " --flag -F 'Hello' --"
    ===args===
    flag_set is       "1"
    flag_with_arg is  "Hello"
    opt_flag is       ""
    ===~~~~===
    remaining_args is ""
    
    Test with: --flagWithArg="Hola" -O"Bird is a Fake" some_extra_args
    optional flag is present!
    args are: " --flagWithArg 'Hola' -O 'Bird is a Fake' -- 'some_extra_args'"
    ===args===
    flag_set is       "0"
    flag_with_arg is  "Hola"
    opt_flag is       "Bird is a Fake"
    ===~~~~===
    remaining_args is "some_extra_args"
    
    You can chain some of the short options together (but why tho?)$normal
    Test with: -fF"Hello!" -O"Bird is a Fake" some_extra_args
    optional flag is present!
    args are: " -f -F 'Hello!' --optionalFlag 'Bird is a Fake' -- 'some_extra_args'"
    ===args===
    flag_set is       "1"
    flag_with_arg is  "Hello!"
    opt_flag is       "Bird is a Fake"
    ===~~~~===
    remaining_args is "some_extra_args"
    
    
    **NOTE: short flags and their argument must mot be separated by any white space:
    Test with: --flagWithArg "This is fine" -O "This is not :("
    args are: " --flagWithArg 'This is fine' -O '' -- 'This is not :('"
    ===args===
    flag_set is       "0"
    flag_with_arg is  "This is fine"
    opt_flag is       ""
    ===~~~~===
    remaining_args is "This is not :("

See also: this post

Reasons:
  • Blacklisted phrase (1): :(
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Low reputation (1):
Posted by: fcb87af7ce6f48c7b98e70a507