Search code examples
linuxbashshellunixgetopts

using a combination of positional parameters and 1 named parameter


I am still "baking" my shell with these features so my question may not sound like "totally ready" ..its more of a "whats the best way to design this" as against something like "I ran into this error or this wont work..now what do I do ", so bear with me pl. while I explain
I am thinking of a shell program which can be run in 2 modes

  • Standard Mode is a bunch of positional parameters
    e.g. myprogram date1 date2 date3 date4 # can go on indefinitely
  • Named Parameter mode
    myprogram -r date1 # Just 1 date para allowed

They are of course mutually exclusive myprogram date1 date2 date3 date4 is ok
myprogram -r date1 date2 date3 date4 is not because 1 only parameter is expected with -r

I am aware of getopts offering a named parameter feature that can shift through a bunch of options.
I have the standard mode ready & working and would like to "add" to the code to get the named parameter mode
In standard mode my code is patterned like

for args
do
stuff that I want done here 
shift
done

So here is what I am thinking for the named parameter mode logic
(When I use getopts and more that 1 positional parameters is used It should quit. )
With getopts allowing just 1 parameter, I am thinking of some like this

while getopts "r:"  opt; 
do
case statement of getopts 
<stuff I want to do >
esac 
done


and for limiting positional paras to just 1 I should have something like this ?
[ "$#" -eq 2 ] || die " more than 1 para not expected here"
the 2 is because while i am in the while loop above , -r is the 1st pos. para and 1 para is the variable one that gets in there. I have to do the checking within the loop because , I want it to fall through without anything being done if -r option is not used , in which case I can have as many pos parameters as I need
So how do I cook this best- is what I am trying to understand. Put the getopts code 1st and then follow through with the positional parameter code ? Sorry if I could be too specific in my question.


Solution

  • I don't always use getopts, but when I do, it looks something like this:

    ...
    
    #Defaults
    Verbose=false
    ropt=false
    
    # Options
    while getopts vr: opt; do
      case "$opt" in
        v)  Verbose=true; vopt="-v" ;;
        r)  ropt=true; rarg="$OPTARG" ;;
        *)  usage; exit 1 ;;
      esac
    done
    shift $((OPTIND - 1))
    
    if $ropt && [ $# -gt 0 ]; then
      $Verbose && echo "Too many arguments. Bye." >&2
      exit 1
    elif $ropt; then
      args=( "$rarg" )
    else
      args=( "$@" )
    fi
    
    # then...
    for thing in "$args"; do
      ... something with $thing ...
    done
    

    The first condition after the getopts loop controls whether you're running in multi-argument or single argument (-r) mode. The subsequent elses populate the $args array, which you can then do whatever you like with later.