美文网首页
命令行参数处理函数getopt和getopts

命令行参数处理函数getopt和getopts

作者: CodingCode | 来源:发表于2021-08-08 01:52 被阅读0次

命令行参数处理函数getopt和getopts

  1. getopt

getopt是一个外部命令,作用是分析输入参数,转换成格式化的输出字符串。

opts=`getopt -o abc:d: --long aa,bb,cc:,dd: -n "myscript" -- "$@"`
if [ $? != 0 ] ; then echo "Failed parsing options." >&2; exit 1; fi
eval set -- "$OPTS"

举一个例子来说明这个问题:

opts=`getopt -o abc:d: --long aa,bb,cc:,dd: -n "myscript" -- "$@"`
echo "opts=[$opts]"

运行:

$ test.sh -abc ccc -d "ddd1 ddd2"
opts=[ -a -b -c 'ccc' -d 'ddd1 ddd2' --]

结果就是把参数进行了格式化处理,把-abc <cvalue>分解成独立的-a -b -c <cvalue>这种标准格式。
方便后面的程序处理参数。

错误的处理:

  1. 无效参数

getopt打印出错误信息,并返回非零值。

$ opts=`getopt -o :abc:d: --long aa,bb,cc:,dd: -n "myscript" -- "$@"`
if [ $? != 0 ] ; then echo "Failed parsing options." >&2; exit 1; fi

运行:

$ test.sh -abc ccc -d "ddd1 ddd2" -e
myscript: invalid option -- 'e'
Failed parsing options.

参数-e是一个不支持的参数。

  1. 缺少参数值

再运行

$ test.sh -abc ccc -d
myscript: option requires an argument -- 'd'
Failed parsing options.

参数-d需要带一个参数值,但是没有。

但是这里有一个坑:
如果参数不是最后一个参数,那么getopt会把后一个参数名认定是前一个参数的值。

$ test.sh -abc -d dddd
opts=[ -a -b -c '-d' -- 'dddd']

参数-c需要带一个参数值,但是这里没有,于是getopt把-d认作是-c的参数值了,然后往后只能把dddd认作是位置参数了。

  1. 忽略错误消息

方法是在参数列表最前面加一个冒号(:),然后getopt就不打印出错误信息,但是getopt的返回值还是非零值,脚本还能判断是否继续。

opts=`getopt -o :abc:d: --long aa,bb,cc:,dd: -n "myscript" -- "$@"`
if [ $? != 0 ] ; then echo "Failed parsing options." >&2; exit 1; fi

运行:

$ test.sh -abc ccc -d
Failed parsing options.

前面我们看到参数-d缺少参数值,加了(:)不显示错误信息了,但是getopt命令返回值还是非零,脚本还能从返回值决定后续的操作,

  1. getopts

getopts是一个builtin命令,而不是一个外部程序。

getopts OPTSTRING VARNAME [ARGS...]

如果可选参数[ARGS...]为空,那么读的就是命令行参数"$@"。

典型用法式用在一个循环里面分析命令行参数:

while getopts  "abc:d:" ARG; do
  echo "ARG=[$ARG], OPTIND=[$OPTIND] OPTARG=[$OPTARG]"
done

每一次循环返回一个当前参数放入变量flag中,并同时设置全局变量OPTIND和OPTARG表示下一个处理的参数的位置和当前参数值。
运行:

$ test.sh -a -b -c ccc -d "ddd1 ddd2"
ARG=[a], OPTIND=[2] OPTARG=[]
ARG=[b], OPTIND=[3] OPTARG=[]
ARG=[c], OPTIND=[5] OPTARG=[ccc]
ARG=[d], OPTIND=[7] OPTARG=[ddd1 ddd2]

$ test.sh -abc ccc -d "ddd1 ddd2"
ARG=[a], OPTIND=[1] OPTARG=[]
ARG=[b], OPTIND=[1] OPTARG=[]
ARG=[c], OPTIND=[3] OPTARG=[ccc]
ARG=[d], OPTIND=[5] OPTARG=[ddd1 ddd2]

对错误的处理:
不管是不认识的参数,还是参数缺少参数值,getops都会打印错误信息,并把ARG置成一个问号(?):

$ test.sh -abc ccc -e
ARG=[a], OPTIND=[1] OPTARG=[]
ARG=[b], OPTIND=[1] OPTARG=[]
ARG=[c], OPTIND=[3] OPTARG=[ccc]
test.sh: illegal option -- e
ARG=[?], OPTIND=[4] OPTARG=[]

$ test.sh -abc ccc -d
ARG=[a], OPTIND=[1] OPTARG=[]
ARG=[b], OPTIND=[1] OPTARG=[]
ARG=[c], OPTIND=[3] OPTARG=[ccc]
test.sh: option requires an argument -- d
ARG=[?], OPTIND=[4] OPTARG=[]

如何隐藏错误:同样的在参数列表最前面加一个冒号(:):

while getopts  ":abc:d:" ARG; do
  echo "ARG=[$ARG], OPTIND=[$OPTIND] OPTARG=[$OPTARG]"
done

运行:

$ test.sh -abc ccc -e
ARG=[a], OPTIND=[1] OPTARG=[]
ARG=[b], OPTIND=[1] OPTARG=[]
ARG=[c], OPTIND=[3] OPTARG=[ccc]
ARG=[?], OPTIND=[4] OPTARG=[e]

$ test.sh -abc ccc -d
ARG=[a], OPTIND=[1] OPTARG=[]
ARG=[b], OPTIND=[1] OPTARG=[]
ARG=[c], OPTIND=[3] OPTARG=[ccc]
ARG=[:], OPTIND=[4] OPTARG=[d]

这里就不会打印出错误信息了,但是用户程序还是能够继续处理这种场景的。

  • 对于不支持的参数,返回ARG是一个问号(?),并且OPTARG包含不支持的参数名。
  • 对于缺失参数值的参数,返回ARG是一个冒号(:),并且OPTARG包含此的参数名。

一个比较完整的例子:

while getopts ":abc:d:" opt; do
  case ${opt} in
    a ) echo "opt=$opt" ;;
    b ) echo "opt=$opt" ;;
    c ) echo "opt=$opt,value=$OPTARG" ;;
    d ) echo "opt=$opt,value=$OPTARG" ;;
    : ) echo "Invalid option: $OPTARG requires an argument" 1>&2 ;;
    \? ) echo "Invalid option: $OPTARG" 1>&2 ;;
  esac
done
shift $((OPTIND -1))
echo "positional args=[$@]"

相关文章

网友评论

      本文标题:命令行参数处理函数getopt和getopts

      本文链接:https://www.haomeiwen.com/subject/fqunvltx.html