Command line argument validation library for Bash

2020-05-24 07:34发布

问题:

I am looking for a reusable code snippet that does command line argument validation for bash.

Ideally something akin to the functionality offered by Apache Commons CLI:

Commons CLI supports different types of options:

  • POSIX like options (ie. tar -zxvf foo.tar.gz)
  • GNU like long options (ie. du --human-readable --max-depth=1)
  • Short options with value attached (ie. gcc -O2 foo.c)
  • long options with single hyphen (ie. ant -projecthelp)
  • ...

and it generates a "usage" message for the program automatically, like this:

usage: ls
 -A,--almost-all          do not list implied . and ..
 -a,--all                 do not hide entries starting with .
 -B,--ignore-backups      do not list implied entried ending with ~
 -b,--escape              print octal escapes for nongraphic characters
    --block-size <SIZE>   use SIZE-byte blocks
 -c                       with -lt: sort by, and show, ctime (time of last
                          modification of file status information) with
                          -l:show ctime and sort by name otherwise: sort
                          by ctime
 -C                       list entries by columns

I would include this code snippet at the beginning of my Bash scripts and reuse it across scripts.

There must be something like this. I don't believe we are all writing code to this effect or similar:

#!/bin/bash

NUMBER_OF_REQUIRED_COMMAND_LINE_ARGUMENTS=3

number_of_supplied_command_line_arguments=$#

function show_command_usage() {
  echo usage:
  (...)
}

if (( number_of_supplied_command_line_arguments < NUMBER_OF_REQUIRED_COMMAND_LINE_ARGUMENTS )); then
  show_command_usage
  exit
fi

...

回答1:

This is the solution I use (found it on the net somewhere, probably here itself, don't remember for sure). Please note that the GNU getopt (/usr/bin/getopt) does support single dash long options (ant -projecthelp style) using the option -a, however I haven't used it so it is not shown in the example.

This code parses for 3 options: --host value or -h value, --port value or -p value and --table value or -t value. In case the required parameter isn't set, a test for it is

# Get and parse options using /usr/bin/getopt
OPTIONS=$(getopt -o h:p:t: --long host:,port:,table: -n "$0" -- "$@")
# Note the quotes around `$OPTIONS': they are essential for handling spaces in 
# option values!
eval set -- "$OPTIONS"

while true ; do
    case "$1" in
            -h|--host) HOST=$2 ; shift 2 ;;
            -t|--table)TABLE=$2 ; shift 2 ;;
            -p|--port)
                    case "$2" in
                            "") PORT=1313; shift 2 ;;
                            *)  PORT=$2; shift 2 ;;
                    esac;;
            --) shift ; break ;;
            *) echo "Internal error!" ; exit 1 ;;
    esac
done
if [[ -z "$HOST" ]] || [[-z "$TABLE" ]] || [[ -z "$PORT" ]] ; then
    usage()
    exit
if

An alternative implementation using the getopts shell builtin(this only supports small options):

while getopts ":h:p:t:" option; do
    case "$option" in
         h) HOST=$OPTARG ;;
         p) PORT=$OPTARG ;;
         t) TABLE=$OPTARG ;;
        *) usage(); exit 1 ;;
    esac
done
if [[ -z "$HOST" ]] || [[-z "$TABLE" ]] || [[ -z "$PORT" ]] ; then
    usage()
    exit
if

shift $((OPTIND - 1))

Further reading for GNU getopt and getopts bash builtin



标签: bash shell