This is a little tutorial that I found in my search to learn how to use getopt (mind: not getopts, which is a completely different thing). I want to share it here because I find it refreshingly to the point. Just the main code block already tells almost the whole story:

#!/bin/bash
# Set some default values:
ALPHA=unset
BETA=unset
CHARLIE=unset
DELTA=unset

usage()
{
  echo "Usage: alphabet [ -a | --alpha ] [ -b | --beta ]
                        [ -c | --charlie CHARLIE ] 
                        [ -d | --delta   DELTA   ] filename(s)"
  exit 2
}

PARSED_ARGUMENTS=$(getopt -a -n alphabet -o abc:d: --long alpha,bravo,charlie:,delta: -- "$@")
VALID_ARGUMENTS=$?
if [ "$VALID_ARGUMENTS" != "0" ]; then
  usage
fi

echo "PARSED_ARGUMENTS is $PARSED_ARGUMENTS"
eval set -- "$PARSED_ARGUMENTS"
while :
do
  case "$1" in
    -a | --alpha)   ALPHA=1      ; shift   ;;
    -b | --beta)    BETA=1       ; shift   ;;
    -c | --charlie) CHARLIE="$2" ; shift 2 ;;
    -d | --delta)   DELTA="$2"   ; shift 2 ;;
    # -- means the end of the arguments; drop this, and break out of the while loop
    --) shift; break ;;
    # If invalid options were passed, then getopt should have reported an error,
    # which we checked as VALID_ARGUMENTS when getopt was called...
    *) echo "Unexpected option: $1 - this should not happen."
       usage ;;
  esac
done

echo "ALPHA   : $ALPHA"
echo "BETA    : $BETA "
echo "CHARLIE : $CHARLIE"
echo "DELTA   : $DELTA"
echo "Parameters remaining are: $@"

Just be sure to correct the inadvertent mixing of beta and bravo.

  • MonkderVierte@lemmy.zip
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    7 hours ago

    I’ve got one from stackoverflow i tidied up and expanded, that handles long options as well, but you really should learn Python instead. Talking from experience; even with a state machine approach and helpful little functions and debug helpers, juggling so much input is hard in shell.

    Well, you’re warned now and here it is:

    tool_name="tool"
    tool_descr="tool does tool things"
    
    printhelp() {
    	printf '%s\nSyntax: %s [options]...\n%s\n' "$tool_descr" "$tool_name" "$tool_args"
    }
    bool() { [ -n "$OPTARG" ] && error "--${OPT} accepts no parameters" 7; }
    # cli-parser
    #--------------------------------------------------------------
    tool_args='
      -s, --stuff          stuff to do
      -o, --other          other stuff to do
    
      -V, --verbose        Tell what i do
      -v, --version        Print version of this tool and exit
      -h, --help           This help text
    '
    while getopts "vVhbs:o:-:" OPT; do
    	# support long options: https://stackoverflow.com/a/28466267/519360
    	if [ "$OPT" = "-" ]; then           # long option: reformulate OPT and OPTARG
    		OPT="${OPTARG%%=*}"             # extract long option name
    		OPTARG="${OPTARG#"$OPT"}"       # extract long option argument (may be empty)
    		OPTARG="${OPTARG#=}"            # if long option argument, remove assigning `=`
    	fi
    	case "$OPT" in
    		s | stuff )       arg_stuff="$OPTARG"
    	;;  o | other )       arg_other="$OPTARG"
    	;;  V | verbose )     bool; verbose=true
    	;;  v | version )     bool; printversion; exit 0
    	;;  h | help )        printhelp; exit 0
    	;;  ??* )             error "Illegal option --$OPT" 22  # bad long option
    	;;  : )               exit 2                            # missing parameter (error reported via getopts)
    	;;  ? )               exit 22                           # bad short option (error reported via getopts)
    	esac
    done
    [ $OPTIND -eq 1 ] && \
    if { [ -e "$1" ] && [ $# -gt 0 ]; }                         # check for lazy file argument
    	then lazy_arg="$1"
    	else printhelp && exit 0
    fi
    shift $((OPTIND-1)) # remove parsed options and args from $@ list
    
  • SubArcticTundra@lemmy.ml
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    15 hours ago

    I still think my favorite shell, NuShell, handles this the best:

    def alphabet [
        --alpha (-a)
        --charlie (-c): string    # comments on these lines are parsed and used for automatically generated --help flag
        --delta: int
        ...filenames: string
    ] { echo \$alpha }"
    

    So much less boilerplate

  • FizzyOrange@programming.dev
    link
    fedilink
    English
    arrow-up
    5
    ·
    19 hours ago

    If you find yourself needing this, the correct thing to do is to stop writing that shell scripts and switch to a proper language.

    • tjhowse@lemmy.world
      link
      fedilink
      English
      arrow-up
      7
      ·
      19 hours ago

      While I agree with you, I think it’s a bit unkind to reply in this way. Sometimes bash is all you have, and it’s interesting to learn about tools even if you’re unlikely to use them.