# Functions for scanning command line options

I know that getopts is available but I wanted to write my own as a way of improving my bash. Below I show two function definitions and an example of the use of them in a bash script. Finally I show the output of the script.

#!/bin/bash
# Produce a string variable which can be used by function isoption
# to give calling scripts an easy way to determine what options are
# are provided in its command line regardless of their order.
# Call this function as:
#
#   mygetopts "$@" # # Non-option arguments in the command line of the caller are # passed back to the caller in array NONOPTARGS and can be used like this: # # name=NONOPTARGS[0] # # NOTE: Option globbing is not allowed function mygetopts () { # Initialize a string variable which will be made to contain all # option names in "$@".  Since this string will be used by function
# isoption a weird variable name is used to avoid collision with
# variable names in calling script since it cannot be made local.

O1P2T3I4O5N6="-"    # O1P2T3I4O5N6 is avaiable to caller
declare -i i=0      # i is local to function

if [[ "$1" == "-h" || "$1" == "--help" ]]; then
echo "Usage: $0 \"$@\"" >&2 return 1 fi for arg in "@" ; do # arg will be each positional parameter if [[ {arg:0:1} == - ]] # if arg begins with - # Pack all option names separated by - then O1P2T3I4O5N6={O1P2T3I4O5N6}{arg:1}- else NONOPTARGS[i++]=arg fi #echo "O1P2T3I4O5N6 =O1P2T3I4O5N6" #echo "NONOPTARGS = {NONOPTARGS[@]}" done return 0 } function isoption () { if [[ O1P2T3I4O5N6 =~ ^.*-{1}-.* ]] then return 0 else return 1 fi }  #!/bin/bash # Example of using functions mygetopts and isoption to provide easy # access to all command line options as well as non-option arguments # regardless of their order. # # To use these functions place the file MYFUNCTIONS in your HOME # directory and source it in your bash script before using the # functions. Alternately it can be sourced by your .bash_profile set +vx # Change + to - to enable tracing echo echo These # command line arguments are provided: echo "@" . ~/MYFUNCTIONS # source the function definitions echo echo These functions are defined: compgen -A function # Show what functions are defined echo mygetopts "@" # Call mygetopts with all command line arguments echo mygetopts returns this string with all options separated by - echo O1P2T3I4O5N6 = O1P2T3I4O5N6 # Show the string of all options echo Examples of the use of isoption function: if isoption f; then echo f found ; else echo f Not found; fi if isoption z; then echo z found ; else echo z Not found; fi if isoption abcd; then echo abcd found ; else echo abcd Not found; fi if isoption abcde; then echo abcde found ; else echo abcde Not found; fi echo echo Examples of the accessing of non-option arguments: inputfilename={NONOPTARGS[0]} outputfilename={NONOPTARGS[1]} echo inputfilename=inputfilename echo outputfilename=outputfilename  ***13:00:47 617 ~/work>testmygetopts -bde -f infile -abcd -x outfile -y  These 7 command line arguments are provided: -bde -f infile -abcd -x outfile -y These functions are defined: • isoption • mygetopts mygetopts returns this string with all options separated by - O1P2T3I4O5N6 = -bde-f-abcd-x-y-  Examples of the use of isoption function: f found z Not found abcd found abcde Not found  Examples of the accessing of non-option arguments: inputfilename=infile outputfilename=outfile  ## 2 Answers The bash code all looks reasonably fine to me. The -h and --help output doesn't look right (it will print the actual parameters passed, but should print the list of allowable options/parameters?) Options like --this-will-break won't work with --will or --break. I'm not clear if parameters with spaces in them will work, as in: testmygetopts "this is one argument" I think 'isoption' could be simplifed to just be the [[ ]] expression (since it will return 0 or 1 already). declare -i i=0 # i is local to function  Inside a function declare and local do the same thing, but if you're going to write a code comment saying it's local, don't you think the local keyword is more self-documenting? I'd write it… local -i i=0 if [[ "1" == "-h" || "1" == "--help" ]]; then  This is fine, but you don't actually need double quotes inside a double-bracket test. You don't need the double-equals either. That's up to you. echo "Usage: 0 \"$@\"" >&2  Use printf and single quotes for better readability. You immediately know the "$@" won't expand in single quotes, and the "$0" gets expanded before printf interpolates it. printf 'Usage: %s "$@"\n' "$0" >&2  for arg in "$@" ; do    # arg will be each positional parameter


Same as for arg without the in "$@" part. Up to you. if [[${arg:0:1} == - ]]    # if $arg begins with -  More efficiently written: if [[$arg = -* ]]


function isoption ()
{

if [[ $O1P2T3I4O5N6 =~ ^.*-${1}-.*$]] then return 0 else return 1 fi }  A nice bash feature is that return always returns the value of$?, so you could write this:

[[ $O1P2T3I4O5N6 =~ ^.*-${1}-.*$]] return  But if you prefer explicit, your code is fine. On to the example part: echo echo These$# command line arguments are provided:
echo "$@"  This use of echo is the only thing I think it actually wrong. Echo takes options (-neE), so you should never give it an unsanitized "$@" to output. Use printf here.

printf '%s ' "\$@"; echo


And the rest is fine. Very nice job!