0

I am not very experienced with getopt, but in all codes I have seen, it is only being used to reorder the program arguments and then use switch/case to decode which options and arguments are being used, therefore usually requiring to parse (or skip) all of them at once.

What if I did not want to do this processing, but treat the options as a dictionary and pick them up when I actually need them? Something like get_option_value -o "x:" which would return either the actual argument value, or true/false for flags.

Obviously, this can be easily done manually and will be always more effective in terms of complexity,but I suppose there is actually this "easy to use" functionality, just I did not stumble upon it.

  • Are you referring to Unix getopt, Linux getopt or bash's built-in getopts? The used tag doesn't match the title of the question. – r_31415 Jun 18 '22 at 05:31
  • What should that magic command do if the script is invoked as -x 1 -x2? Return 1 and 2 as an array or only 2? What if you have a -x and -y one undoing the other, then the order or processing is important. – Stéphane Chazelas Jun 18 '22 at 14:41

2 Answers2

0

Firstly, if you're using bash, run help getopts. That provides a good summary of what getopts is and what it does. Otherwise search for getopts in the man page for your shell.

With that said, it's important to note that getopts does not search for a particular option, it gets the next command line argument (which is always going to be in "$1"). Its up to your script to do something with that option (and its arg if it has one), and remove it/them from the command line.

The optstring isn't a search string, it's a validation string - it tells getopts what options are valid and whether they're supposed to take an argument or not, so that it can either print an error message or allow your script to know that an option processing error has occurred so it can take appropriate action.

If you want to look up particular options at arbitrary times/locations in your script, then you have to do what every other program does and parse the options shortly after the script is executed, and store the results in variables.

i.e. you have to do what you say you don't want to do - there's no other way if you want to use getopts.

There is nothing stopping you from writing your own program or function that searches the command-line for one specific option (and its value, if any), but the reason nobody does it like this is that there's no point - it's easier and more efficient to just parse all the options at once in a loop than to parse/search them as an ad-hoc query (because that search program/function will have to loop over the options and args every time its called, using either getopts or iterating over a copy of the script's "$@" if its a shell function, or using the libc getopt() function if it's a standalone program).

A common way of doing this is to set the variables to their default values (if any), then process each option, changing the variables from the defaults as options are seen.

A very simple example, x and y take arguments, b is a boolean:

x=10
y=20
b=0
while getopts "x:y:b" opt; do
  case "$opt" in
    x) x="$2" ; shift ;;
    y) y="$2" ; shift ;;
    b) b=1 ;;
  esac
  shift
done
echo "x=$x"
echo "y=$y"
echo "b=$b"
cas
  • 78,579
0

You can scan the parameter list with getopts more than once, by (re)setting the OPTIND variable. The bash manual says

getopts is used by shell scripts to parse positional parameters. optstring contains the option characters to be recognized; if a character is followed by a colon, the option is expected to have an argument, which should be separated from it by whitespace. The colon (‘:’) and question mark (‘?’) may not be used as option characters. Each time it is invoked, getopts places the next option in the shell variable name, initializing name if it does not exist, and the index of the next argument to be processed into the variable OPTIND. OPTIND is initialized to 1 each time the shell or a shell script is invoked. When an option requires an argument, getopts places that argument into the variable OPTARG. The shell does not reset OPTIND automatically; it must be manually reset between multiple calls to getopts within the same shell invocation if a new set of parameters is to be used.

It also mentions that you need not use the original set of parameters:

getopts normally parses the positional parameters, but if more arguments are supplied as arg values, getopts parses those instead.

Thomas Dickey
  • 76,765