1# getopt.awk --- Do C library getopt(3) function in awk 2# Also supports long options. 3# 4# Arnold Robbins, arnold@skeeve.com, Public Domain 5# 6# Initial version: March, 1991 7# Revised: May, 1993 8# Long options added by Greg Minshall, January 2020 9 10# External variables: 11# Optind -- index in ARGV of first nonoption argument 12# Optarg -- string value of argument to current option 13# Opterr -- if nonzero, print our own diagnostic 14# Optopt -- current option letter 15 16# Returns: 17# -1 at end of options 18# "?" for unrecognized option 19# <s> a string representing the current option 20 21# Private Data: 22# _opti -- index in multiflag option, e.g., -abc 23function getopt(argc, argv, options, longopts, thisopt, i, j) 24{ 25 if (length(options) == 0 && length(longopts) == 0) 26 return -1 # no options given 27 28 if (argv[Optind] == "--") { # all done 29 Optind++ 30 _opti = 0 31 return -1 32 } else if (argv[Optind] !~ /^-[^:[:space:]]/) { 33 _opti = 0 34 return -1 35 } 36 if (argv[Optind] !~ /^--/) { # if this is a short option 37 if (_opti == 0) 38 _opti = 2 39 thisopt = substr(argv[Optind], _opti, 1) 40 Optopt = thisopt 41 i = index(options, thisopt) 42 if (i == 0) { 43 if (Opterr) 44 printf("%c -- invalid option\n", thisopt) > "/dev/stderr" 45 if (_opti >= length(argv[Optind])) { 46 Optind++ 47 _opti = 0 48 } else 49 _opti++ 50 return "?" 51 } 52 if (substr(options, i + 1, 1) == ":") { 53 # get option argument 54 if (length(substr(argv[Optind], _opti + 1)) > 0) 55 Optarg = substr(argv[Optind], _opti + 1) 56 else 57 Optarg = argv[++Optind] 58 _opti = 0 59 } else 60 Optarg = "" 61 if (_opti == 0 || _opti >= length(argv[Optind])) { 62 Optind++ 63 _opti = 0 64 } else 65 _opti++ 66 return thisopt 67 } else { 68 j = index(argv[Optind], "=") 69 if (j > 0) 70 thisopt = substr(argv[Optind], 3, j - 3) 71 else 72 thisopt = substr(argv[Optind], 3) 73 Optopt = thisopt 74 i = match(longopts, "(^|,)" thisopt "($|[,:])") 75 if (i == 0) { 76 if (Opterr) 77 printf("%s -- invalid option\n", thisopt) > "/dev/stderr" 78 Optind++ 79 return "?" 80 } 81 if (substr(longopts, i+1+length(thisopt), 1) == ":") { 82 if (j > 0) 83 Optarg = substr(argv[Optind], j + 1) 84 else 85 Optarg = argv[++Optind] 86 } else 87 Optarg = "" 88 Optind++ 89 return thisopt 90 } 91} 92BEGIN { 93 Opterr = 1 # default is to diagnose 94 Optind = 1 # skip ARGV[0] 95 96 # test program 97 if (_getopt_test) { 98 _myshortopts = "ab:cd" 99 _mylongopts = "longa,longb:,otherc,otherd" 100 101 while ((_go_c = getopt(ARGC, ARGV, _myshortopts, _mylongopts)) != -1) 102 printf("c = <%s>, Optarg = <%s>\n", _go_c, Optarg) 103 printf("non-option arguments:\n") 104 for (; Optind < ARGC; Optind++) 105 printf("\tARGV[%d] = <%s>\n", Optind, ARGV[Optind]) 106 } 107} 108