[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Handling options with optional arguments with getopts
From: |
nigelberlinguer |
Subject: |
Handling options with optional arguments with getopts |
Date: |
Sat, 28 Aug 2021 00:01:51 +0000 |
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Friday, August 27, 2021 8:52 PM, Robert Elz <kre@munnari.OZ.AU> wrote:
> Date: Fri, 27 Aug 2021 17:20:39 +0000
> From: nigelberlinguer <nigelberlinguer@protonmail.com>
>
> Message-ID:
> <MXe0alzC7mwCcivJXNfR4tp7vhikdlq89AZeQHl5yLYKqiEH54YiugyWaTtN2aRkpgcWC6tjkCOCt41IrbPIgx_jMoAkfRzo3NMLvTqV_oE=@protonmail.com>
>
>
> | It should be noted though, that the POSIX requirement by "Guideline 7"
> | is not guided by actual portability in the technical sense but by a
> | rule written in the POSIX standard.
>
> Those guidelines serve two purposes - they indicate what should be the
> arg format for posix standard utilities, and they specify what must be
> handled for those cases where they are specified to apply (as in getopts).
>
> | Perhaps there should be an update
> | to POSIX on what is actually portable or not
>
> There are constantly updates to POSIX - but I don't see anything likely to
> change in this area. "Works in bash" is not the definition of portable.
>
> In general, what POSIX specifies (with just a few exceptions, which
> often don't matter) is what you can rely upon working - as soon as you
> start using anything not specified by POSIX, or explicitly said
> to be unspecified or undefined, then you cannot really expect the
> code (including scripts) to work on other systems, and perhaps not
> even on later versions of the system you're using.
Would parsing things yourself be made portable ?
> | I have seen the following workaround, where tho options that allows an
> | optional argument is defined with no arguments in shortopts.
> |
> | local vb=1 sort=0
> |
> | local OPTIND OPTARG
> | local shortopts="Vuhvs"
> | while getopts $shortopts arg; do
> | case $arg in
> | ("V") printf '%s\n' "Version" ; return ;;
> | ("u") printf '%s\n' "usage" ; return ;;
> | ("h") printf '%s\n' "help" ; return ;;
> | ("v")
> | # Allows argument to be optional.
> | # Defines option with no arguments in shortopts.
> | nextarg=${!OPTIND}
> | if [[ (-n "$nextarg") && ("$nextarg" != -*) ]] ; then
> | OPTIND=$((OPTIND + 1))
> | vb="$nextarg"
>
> Aside from using bash private syntax (which could be mostly avoided there
> if one had the desire) that kind of use of OPTIND is certainly not portable.
> The only defined write operation on OPTIND is to set it to 1.
>
> Further, even where something like that does work, it provides no mechanism
> for the arg to the option to begin with a '-', which might not matter in
> some cases, but certainly isn't very general.
One can check amongst the options defined, and allow everything else.
> | I also wonder whether the "shift" command is used with `getopts`.
>
> No. Or not inside the loop. Once the loop is finished, the code
> should usually do
>
> shift $(( ${OPTIND} - 1 ))
>
> to remove all the args that have been processed by getopts - but that's
> not always required (there are other ways to get the remaining args, if
> any, if they are needed, but doing the shift means the remaining args are
> "$@").
>
> Altering the arg list (in any way at all) during getopts processing produces
> unspecified results.
>
> | I see people use the `shift` command when doing their own parsing;
>
> Yes, that's often the easiest way to do it for hand rolled parsing
> (it means that what you're currently examining is always $1, and so
> there's no need to write messy code to get at a variable positional param,
> which is not trivial to do portably).
>
> | and when others use `getopt`.
>
> getopt is obsolete, and has numerous failure modes. But yes, shift
> is used when using getopt (getopt is generally implemented as an
> external command, and so cannot affect the state of the shell, including
> any shell variables, getopts is always a shell builtin command).
>
> kre