3
\$\begingroup\$

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.

Please comment.

#!/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
sepp2k
9,0122 gold badges39 silver badges51 bronze badges
asked Jun 5, 2011 at 23:54
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

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).

answered Sep 27, 2011 at 9:24
\$\endgroup\$
2
\$\begingroup\$

...

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!

answered Nov 26, 2011 at 14:08
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.