shell的参数解析
getopt
使用规则
bash或zsh getopt_demo.sh 一堆参数 # 其前中后均可有 余参数
- 格式化参数:即
-
开头的参数,若无法依照希望的方式解析,就会报错
短参数 | 长参数 | |
---|---|---|
无选项 | -a | –a-long |
必有选项 | -boption 或 -b option 或 -b'op tions' 或 -b 'op tion' |
--b-long option 或--b-long 'op tion' |
可有选项 若无选项 | -c |
--c-long |
可有选项 若有选项: 只能用短参数 选项和参数间无空格 |
-coption -c'op tion' |
--c-long option 不可 |
- 余参数:即非
-
开头的参数,可出现在格式化参数之前、之中、之后
例如
bash/zsh getopt_demo.sh -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
返回
Option a
Option c, no argument
Option c, argument more'
Option b, argument very long '
Remaining arguments:
--> par1'
-->another arg'
--> `wow!\?'
代码写法
getopt_demo.sh
内容如下
#!/bin/bash
# 使用规则
# bash/zsh getopt_demo.sh 一堆参数,其前中后均可有 余参数
# 格式化参数:以'-'开头,必需符合本代码的解析要求
# 短参数 长参数
# 无选项 -a --a-long
# 必有选项 -bss -b ss --b-long ss
# -b'sds sds' -b 'sds sds' --b-long 'sds sds'
# 可有选项若无 -c --c-long
# 可有选项若有 -css -c'sds sds' 只可短参数,选项与参数间不得有空格
# 余参数:不以'-'开头
# 参数预处理
TEMP=$(getopt \
-o ab:c:: \
--long a-long,b-long:,c-long:: \
-n '参数解析错误' \
-- s "$@")
# 写法
# -o 短参数 不需要分隔符
# --long 长参数 用','分隔
# ``无选项 `:`必有选项 `::` 可由选项
if [ $? != 0 ] ; then echo "格式化的参数解析错误,正在退出" >&2 ; exit 1 ; fi
eval set -- "$TEMP" # 将复制给 $1, $2, ...
# 处理参数
while true ; do case "$1" in
# 无选项
-a|--a-long) echo opt a ; shift ;;
# 必有选项
-b|--b-long) echo opt b arg "$2" ; shift 2 ;;
# 可省选项
-c|--c-long) case "$2" in
# 无选项
"") echo opt c no arg ; shift 2 ;;
# 有选项
*) echo opt c arg "$2" ; shift 2 ;; esac ;;
# '--'后是 余参数
--) shift ; break ;;
# 处理参数的代码错误
*) echo "参数处理错误" ; exit 1 ;;
esac ; done
# 余下参数
for i in "$@"; do
echo rest "$i"
done
snippets
为了方便些getopt,我已经将上述模板写成sublime、vscode、vim的snippet
徒手解析
while test $# -gt 0; do
case "$1" in
-<短参数1>) 相应代码 ;; # 短参数
-<短参数2>) 相应代码 ;; # 短参数
--<长参数1>) 相应代码 ;; # 长参数
--<长参数2>) 相应代码 ;; # 长参数
-*) 相应代码 ;; # 剩余短参数
--*) 相应代码 ;; # 剩余长参数
*) 相应代码 ;; # 非参数
esac
shift
done
注:
;;
前可以换行,详见下-某某)
后可以换行,详见下- 相应代码可以再接受参数,例如
-<短参数1>)
if [ "${2:0:1}" != '-' ]; then
相应代码来处理$2
shift
fi
;;
缺点:
- 仅此一个:不支持解析相邻的短参数
-lAd
,必需写成-l -A -d