1 #From: "Grigoriy Strokin" <grg@philol.msu.ru>
2 #Newsgroups: comp.unix.shell
3 #Subject: BASH: getopt function that parses long-named options
4 #Date: Mon, 22 Dec 1997 20:35:18 +0300
6 #Hi, I have written a BASH function named getoptex, that is like bash builtin
7 #"getopts", but does parse long-named options and optional arguments. It only
8 #uses builtin bash commands, so it is very fast. In order to use it in your
9 #bash scripts, include a command ". getopt.sh" (<dot> getopt.sh) to the file
10 #containing your script, and that will define functions getopt, getoptex, and
11 #optlistex (the file getopt.sh with its detailed description is listed
14 #*** file getopt.sh ***
19 # functions like getopts but do long-named options parsing
20 # and support optional arguments
22 # Version 1.0 1997 by Grigoriy Strokin (grg@philol.msu.ru), Public Domain
23 # Date created: December 21, 1997
24 # Date modified: December 21, 1997
28 # 1) Parses both short and long-named options
29 # 2) Supports optional arguments
30 # 3) Only uses bash builtins, thus no calls to external
31 # utilities such as expr or sed is done. Therefore,
32 # parsing speed is high enough
38 # Usage: getopt OPTLIST {"$@"|ALTERNATIVE_PARAMETERS}
40 # like getopts, but parse options with both required and optional arguments,
41 # Options with optional arguments must have "." instead of ":" after them.
42 # Furthemore, a variable name to place option name cannot be specified
43 # and is always placed in OPTOPT variable
45 # This function is provided for compatibility with getopts()
46 # OPTLIST style, and it actually calls getoptex (see bellow)
48 # NOTE that a list of parameters is required and must be either "$@",
49 # if processing command line arguments, or some alternative parameters.
52 # Usage: getoptex OPTION_LIST {"$@"|ALTERNATIVE_PARAMETERS}
54 # like getopts, but parse long-named options.
56 # Both getopt and getoptex return 0 if an option has been parsed,
57 # and 1 if all options are already parsed or an error occured
59 # Both getopt and getoptex set or test the following variables:
61 # OPTERR -- tested for whether error messages must be given for invalid
64 # OPTOPT -- set to the name of an option parsed,
65 # or to "?" if no more options or error
66 # OPTARG -- set to the option argument, if any;
67 # unset if ther is no argument;
68 # on error, set to the erroneous option name
70 # OPTIND -- Initialized to 1.
71 # Then set to the number of the next parameter to be parsed
72 # when getopt or getoptex will be called next time.
73 # When all options are parsed, contains a number of
74 # the first non-option argument.
77 # OPTOFS -- If a parameter number $OPTIND containg an option parsed
78 # does not contain any more options, OPTOFS is unset;
79 # otherwise, OPTOFS is set to such a number of "?" signs
80 # which is equal to the number of options parsed
82 # You might not set variables OPTIND and OPTOFS yourself
83 # unless you want to parse a list of parameters more than once.
84 # Otherwise, you whould unset OPTIND (or set it to 1)
85 # and unset OPTOFS each time you want to parse a new parameters
88 # Option list format is DIFFERENT from one for getopts or getopt.
90 # option list can be converted to getoptex-style using a function optlistex
93 # DESCRIPTION of option list used with getoptex:
94 # Option names are separated by whitespace. Options consiting of
95 # more than one character are treated as long-named (--option)
97 # Special characters can appear at the and of option names specifying
98 # whether an argument is required (default is ";"):
99 # ";" (default) -- no argument
100 # ":" -- required argument
101 # "," -- optional argument
103 # For example, an option list "a b c help version f: file: separator."
104 # defines the following options:
105 # -a, -b, -c, --help, --version -- no argument
106 # -f, --file -- argument required
107 # --separator -- optional argument
110 # Usage new_style_optlist=`optlistex OLD_STYLE_OPTLIST`
112 # Converts getopts-style option list in a format suitable for use with getoptex
113 # Namely, it inserts spaces after each option name.
118 # In order o use in your bash scripts the functions described,
119 # include a command ". getopt.sh" to the file containing the script,
120 # which will define functions getopt, getoptex, and optlistex
124 # See files 'getopt1' and 'getopt2' that contain sample scripts that use
125 # getopt and getoptex functions respectively
128 # Please send your comments to grg@philol.msu.ru
133 local optlist
="${1#;}"
134 let OPTIND || OPTIND
=1
135 [ $OPTIND -lt $# ] ||
return 1
137 if [ "$1" != "-" ] && [ "$1" != "${1#-}" ]
138 then OPTIND
=$
[OPTIND
+1]; if [ "$1" != "--" ]
142 for opt
in ${optlist#;}
144 OPTOPT
="${opt%[;.:]}"
146 local opttype
="${opt##*[^;:.]}"
147 [ -z "$opttype" ] && opttype
=";"
148 if [ ${#OPTOPT} -gt 1 ]
149 then # long-named option
152 if [ "$opttype" != ":" ]; then return 0; fi
155 then # error: must have an agrument
156 let OPTERR
&& echo "$0: error: $OPTOPT must have an argument" >&2
161 OPTIND
=$
[OPTIND
+1] # skip option's argument
165 if [ "$opttype" = ";" ];
166 then # error: must not have arguments
167 let OPTERR
&& echo "$0: error: $OPTOPT must not have arguments" >&2
172 OPTARG
=${o#"--$OPTOPT="}
176 else # short-named option
180 [ "$opttype" != ":" ] && return 0
184 echo "$0: error: -$OPTOPT must have an argument" >&2
189 OPTIND
=$
[OPTIND
+1] # skip option's argument
193 if [ $opttype = ";" ]
194 then # an option with no argument is in a chain of options
195 OPTOFS
="$OPTOFS?" # move to the next option in the chain
196 OPTIND
=$
[OPTIND-1
] # the chain still has other options
200 OPTARG
="${o#-$OPTOPT}"
207 echo "$0: error: invalid option: $o"
217 local r
# to store result
218 while [ ${#m} -lt $
[${#l}-1] ]; do m
="$m?"; done # create a "???..." mask
221 r
="${r:+"$r "}${l%$m}" # append the first character of $l to $r
222 l
="${l#?}" # cut the first charecter from $l
223 m
="${m#?}" # cut one "?" sign from m
224 if [ -n "${l%%[^:.;]*}" ]
225 then # a special character (";", ".", or ":") was found
226 r
="$r${l%$m}" # append it to $r
227 l
="${l#?}" # cut the special character from l
228 m
="${m#?}" # cut one more "?" sign
235 local optlist
=`optlistex "$1"`
237 getoptex
"$optlist" "$@"
241 #**************************************
243 #**************************************
244 #*** (end of getopt.sh) ***
247 #*** file getopt1 ***
251 # Sample script using the function getopt
253 # Type something like "getopt1 -ab -d 10 -e20 text1 text2"
254 # on the command line to see how it works
256 # See getopt.sh for more information
258 #echo Using getopt to parse arguments:
259 #while getopt "abcd:e." "$@"
261 # echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}"
266 # echo "Non option argument <$arg>"
269 #**************************************
271 #**************************************
272 #*** (end of getopt1) ***
275 #*** file getopt2 ***
279 # Sample script using the function getoptex
281 # Type something like "getopt2 -ab -d 10 -e20 --opt1 --opt4=100 text1 text2"
282 # to see how it works
284 # See getopt.sh for more information
286 #echo Using getoptex to parse arguments:
287 #while getoptex "a; b; c; d: e. opt1 opt2 opt3 opt4: opt5." "$@"
289 # echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}"
294 # echo "Non option argument <$arg>"
297 #**************************************
299 #**************************************
300 #*** (end of getopt2) ***