Getopt
September 17, 2019
Here is our version of getopt:
function getopt(defn, msg, n, i, flag, rest) {
# collect flag/value pairs in OPTS,
# remove from ARGV, and return count
# initialize i, loop runs forever
for (i = 1; ;) {
# stop at end of arguments
if (i == ARGC) { return n+0 }
if (ARGV[i] == "--") { ARGV[i] = ""; return n+0 }
if (ARGV[i] == "") { i++; continue }
if (substr(ARGV[i],1,1) != "-") { return n+0 }
# found argument; parse flag from rest of string
flag = substr(ARGV[i],2,1); rest = substr(ARGV[i],3)
# argument requires an associated value
if (index(defn, flag ":") > 0) {
if (rest != "") { # value in same argument as flag
OPTS[flag] = rest; ARGV[i] = ""; i++; n++ }
else if (i &2"; exit 1 } }
# argument has no associated value
else if (index(defn, flag) > 0) {
if (rest != "") {
OPTS[flag] = ""; ARGV[i] = "-" rest; n++ }
else { OPTS[flag] = ARGV[i] = ""; n++ } }
# unrecognized flag
else { print "ERROR: unrecognized flag " flag \
": " msg | "cat 1>&2"; exit 1 } } }
There are a few points of interest here. The for loop initializes i but doesn’t increment it, because sometimes i isn’t incremented the same as other times, and doesn’t test for termination, because there are multiple ways to terminate the loop, some of which require different processing. The idiom print ... | "cat 1>&2" prints a message on stderr; in Gawk you can write directly to /dev/stderr, but that is not possible in other implementations of Nawk (for instance, on HP-UX where I work). The return value n+0 coerces n to numeric in case there are no flags.
You can call getopt in the BEGIN action like this:
BEGIN { msg = "usage: [-befhmn] [-D string]"
print "There are", getopt("befhmnD:", msg), "options."
for (flag in OPTS) { print flag, OPTS[flag] } }
Called as awk -f opts.awk -- -b -D hello, that will set two options OPTS["b"] = "" and OPTS["D"] = "hello".
You can run the program at <a href="https://ideone.com/RIk98j"<https://ideone.com/RIk98j.