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 :("
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