Reputation: 21
I have a series of BASH scripts.
I am using getopts to parse arguments from the cmd line (although open to alternatives).
There are a series of common options to these scripts call this options set A ie queue, ncores etc.
Each script then has a series of extra options ie set B1,B2,B3.
What I want is for script
"1 to be able to take options A+B1"
"2 to be able to take options A+B2"
"3 to be able to take options A+B2"
But I want to be able to store the code for options A in a central location (library/function) with having to write out in each script.
What I want is a way to insert generic code in getopts. Or alternatively a way to run getopts twice.
In fact I've done this by having getopts as a function which is sourced.
But the problem is I cant get the unrecognised option to work them. I guess one way would be to remove the arguements from options A from the string before passing to a getopts for B1, B2 , B3 etc ?
Thanks Roger
Upvotes: 1
Views: 505
Reputation: 865
That's a very nice question, to answer which we need to have a good understanding of how getopts
works.
The key point here is that getopts
is designed to iterate over the supplied arguments in a single loop. Thus, the solution to the question is to split the loop between different files rather then running the command twice:
#!/usr/bin/env bash
# File_1
getopts_common() {
builtin getopts ":ab:${1}" ${2} ${@:3} || return 1
case ${!2} in
'a')
echo 'a triggered'
continue
;;
'b')
echo "b argument supplied -- ${OPTARG}"
continue
;;
':')
echo "MISSING ARGUMENT for option -- ${OPTARG}" >&2
exit 1
;;
esac
}
#!/usr/bin/env bash
# File_2
# source "File_1"
while getopts_common 'xy:' OPTKEY ${@}; do
case ${OPTKEY} in
'x')
echo 'x triggered'
;;
'y')
echo "y argument supplied -- ${OPTARG}"
;;
'?')
echo "INVALID OPTION -- ${OPTARG}" >&2
exit 1
;;
':')
echo "MISSING ARGUMENT for option -- ${OPTARG}" >&2
exit 1
;;
*)
echo "UNIMPLEMENTED OPTION -- ${OPTKEY}" >&2
exit 1
;;
esac
done
We start with File_2
since that's where the execution of the script starts:
Instead of invoking getopts
directly, we call it via it's proxy: getopts_common
, which is responsible for processing all common option.
getopts_common
function is invoked with:
A string that defines which options to expect, and where to expect their arguments. This string only covers options defined in File_2
.
The name of the shell-variable to use for option reporting.
A list of the command line arguments. (This simplifies accessing them from inside getopts_common
function.)
Moving on to the sourced file (File_1
) we need to bear in mind that getopts_common
function runs inside the while loop defined in File_2
:
getopts
returns false
if there is nothing left to parse, || return 1
bit insures that getopts_common
function does the same.
The execution needs to move on to the next iteration of the loop when a valid option is processed. Hence, each valid option match ends with continue
.
Silent error reporting (enabled when OPTSPEC starts with :
) allows us to distinguish between INVALID OPTION
and MISSING ARGUMENT
. The later error is specific to the common options defined in File_1
, thus it needs to be trapped there.
For more in-depth information on getopts
, see Bash Hackers Wiki: Getopts tutorial
Upvotes: 1