1

How can I clean up this options parsing code in a Bash function? It is copy-pasted into a number of functions that need to have a simple "-h" flag for printing usage. I would rather have a generic routine with the logical equivalent of

local prefix_opt1
local prefix_opt2
....
__handle_opts "usage message" "additional getopts flags" "prefix"

For example:

local foo_k
local foo_v
__handle_opts "Usage: ${FUNCNAME[0]}" [-k key -v version] widget\nBuild a widget using the key and version." "k:v:" "foo_"

if [[ -z $foo_k ]] ; then
    foo_k="default value"
fi
.....

The functions are to be "sourced" in one's dot-bashrc file.

Here is what the code looks like (note: some of the functions do take options via flags):

function kitten_pet {

  local usage="Usage: ${FUNCNAME[0]} [-h] <kitten>\nPet the kitten."

  ################################################
  local help=0
  local error=0
  local OPTIND
  local opt
  while getopts ":h" opt "$@"
  do
    case $opt in

      h)
        echo -e "$usage"
        help=1
        break
        ;;

      \?)
        echo "Invalid option: -$OPTARG"
        error=1
        break
        ;;
    esac
  done
  if [ $error -gt 0 ] || [ $help -gt 0 ] ; then
    return 1
  fi
  shift $((OPTIND-1))
  ################################################

  if [ $# -lt 1 ]
  then
    echo -e "$usage"
    return 1
  fi

  __kitten_pet "$1"
}

Ordinarily I would use something like node-commander or node-optimist and write the script in JavaScript (or perhaps Python) for scripting needs but I'm trying to make Bash work this time. But Bash is bashing me.

4

1 回答 1

0

向通用选项解析器传递调用脚本将管理的选项列表。

对于要在调用脚本中管理的每个选项,创建一个名为option_X_parser. 这些选项解析器函数应该接受一个可选参数 ($OPTARG),并且应该返回 0(成功)或 1(错误)。

通用选项解析器应该使用其通用选项(例如,“h”、“n”和“v”)以及调用程序提供的选项来构建 shell case 语句。对于那些具有关联选项解析器功能的选项,case 语句应包括选项解析器的调用。

每个配置的选项都应该有一个 case 语句,它应该调用用户提供的函数(如果已定义),或者通过设置全局变量进行一般管理(例如,特定选项opt_X在哪里X)。

例如:

__handle_options "$usage", 'hni:v'

option_h_parser() { echo "$usage"; exit 1 ; } option_n_parser() { norun=1 ; return 0 ; } option_v_parser() { verbose=1 ; return 0 ; } option_i_parser() { insert_at="$1" ; return 0 ; } # invoke with argument

基本上,根据选项字母使用隐含的函数名称。

每个选项解析器的返回值由通用选项处理函数检查。像这样的东西:

function_name="option_${opt}_parser"
if eval "$function_name $OPTARG" ; then
  # option is good
else
  error "'$opt' parser failed."
  exit 2
fi

于 2014-01-08T08:42:47.167 回答