Issue
I am trying to write a function that has optional arguments in a way such that the optional arguments are follow by something like -x
, for example
my_function man_arg1 man_arg2 -n opt_arg1 -o opt_arg2 -x opt_arg3
and I want this to also support callings like
my_function man_arg1 man_arg2 -x opt_arg
In other questions I see people suggesting using getopts but in those answers it seems like you have to specify all the optional arguments when calling the function? Also it still seems unclear to me how you would use getopts for this.
Solution
I am not sure I understood the question correctly, sorry if I don't answer it...
You could use (for example) getopt(1)
, as below, which will allow -x
option to be anywhere.
Please note that optional arguments (man_arg*
) can also be anywhere.
#! /usr/bin/bash
# CMD is the shell-script name without directory (basename)
CMD="${0##*/}"
my_function() {
# Some comments added per OP request
# below variable is used by getopt's "-o" option (short options).
# each letter is a possible option; colon following a letter means this
# option will take a parameter. See getopt(1) for more details.
SOPTS="n:o:x:"
# output of getopt is assigned to TMP. For example, when calling :
# my_function -n n1 a b -o o1 -x x1 c d
# TMP will contain: "-n 'n1' -o 'o1' -x 'x1' -- 'a' 'b' 'c' 'd'"
TMP=$(getopt -o "$SOPTS" -n "$CMD" -- "$@") || exit 1
# assign TMP to positional parameters $1, $2, etc...
eval set -- "$TMP"
unset TMP
while true; do
case "$1" in
-n|-o)
printf "[%s] argument: %s\n" "$1" "$2"
shift
;;
-x)
printf "[-x] argument: %s\n" "$2"
shift
;;
--) # end of options
shift
break
;;
esac
shift
done
nargs=$#
printf "remaining %d args :\n" "$nargs"
for ((i=0; i<nargs; ++i)); do
printf "%d: %s\n" $((i + 1)) "$1"
shift
done
}
my_function "$@"
Examples:
br@lorien:~$ ./test-getopt.bash man_arg1 man_arg2 -n opt_arg1 -o opt_arg2 -x opt_arg3
[-n] argument: opt_arg1
[-o] argument: opt_arg2
[-x] argument: opt_arg3
remaining 2 args :
1: man_arg1
2: man_arg2
br@lorien:~$ ./test-getopt.bash man_arg1 man_arg2 -n opt_arg1 -o opt_arg2 -x opt_arg3 man_arg3 man_arg4
[-n] argument: opt_arg1
[-o] argument: opt_arg2
[-x] argument: opt_arg3
remaining 4 args :
1: man_arg1
2: man_arg2
3: man_arg3
4: man_arg4
br@lorien:~$ ./test-getopt.bash man_arg1 man_arg2 -x opt_arg
[-x] argument: opt_arg
remaining 2 args :
1: man_arg1
2: man_arg2
br@lorien:~$ ./test-getopt.bash -x opt_arg4 man_arg2 -n opt_arg1 -x opt_arg3 man_arg3 man_arg4
[-x] argument: opt_arg4
[-n] argument: opt_arg1
[-x] argument: opt_arg3
remaining 3 args :
1: man_arg2
2: man_arg3
3: man_arg4
EDIT: Rewrote the code into a function, as asked in question.
Answered By - Bruno Answer Checked By - Senaida (WPSolving Volunteer)