shell学习-处理脚本的多参数输⼊
前⾔
对于许多脚本都希望有多个参数的输⼊,对于shell这种脚本更是不例外,⼀般程序的起始函数(main)都会有⼀个args选项代表着输⼊的参数项,那么解析这些参数项⽬就是主要的问题,这⾥有两种解析⽅法解析脚本输⼊的参数:
- ⼀个是通过逻辑遍历所有输⼊参数(主要利⽤’shift’函数或者shell对数组的处理)
- ⼀个是利⽤系统⾃带的函数(getopt)配合shift进⾏格式化解析(不⼀定所有系统都,需要检测⼀下)
使⽤·shift解析脚本的参数输⼊
在shell脚本中,命令$后加⼀些特殊的标记可以取脚本的传⼊参数,如$0取脚本输⼊的第⼀个参数,$1取第⼆个参数等:
参数描述
$0命令本⾝,类似c的argv[0]
$1、$2……第1个参数、第2个参数……
$#参数的个数,不包括$0
$@以列表的形式返回参数列表,不包括$0
$?最后运⾏的命令结束代码
在shell中$1到$9相当于⼀个双向队列,脚本的参数按顺序排⼊1~9这些变量中,若脚本参数多于9个,就需要通过shift函数,让第⼀个参数出队,队列中顺序左移,第10个参数⼊队到$9中,因此shift可以处理脚本超过10个参数的情况,但更多的是⽤来解析脚本多参数
shift可以把参数列表左移1个,同时参数个数会减少1,shift 2可以把参数列表左移2个,同时参数个数会减少2
但有个情况:若只有2个参数,运⾏shift 3 函数会运⾏出错返回1,可以通过$?检查是否执⾏成功
xxx.sh:
shift 3;
echo "$?"
echo "$#"
执⾏
xxx.sh -1 -2
输出
1
2
可以看到,shift并没有执⾏,返回1,参数并没有移动。
因此,在处理脚本参数的时候,必要情况需要判断shift是否成功。当然getopt函数可以很⼤程度的避免这些判断逻辑。
这⾥主要运⽤$#和$@这两个变量即可遍历所有的传⼊参数,在不使⽤getopt这个函数的情况下,要遍历所有的输⼊参数可以参考如下脚本:
until [ $#-eq0 ]
do
case"$1"in
-h|--help) echo "-h or --help";
exit0;;
-a|--along) echo "-a or --along";shift;echo "after shift $#";;
-b|--blong) echo "-b or --blong";
case"$2"in
bval1) echo " b value 1";shift 2;echo "after shift $#";;
bval2) echo " b value 2";shift 2;echo "after shift $#";;
bval3) echo " b value 3";shift 2;echo "after shift $#";;
bval4) echo " b value 4";shift 2;echo "after shift $#";;
#不能判断-b后⾯是否会有别的参数,因此不能直接shift 2
*) shift; echo " unknow b value";
if [ $#-eq0 ];then
exit0;
fi
shift;;
esac;;
-c|--clong) echo "-c or --clong";
case"$2"in
cval1) echo " c value 1";shift 2;;
cval2) echo " c value 2";shift 2;;
cval3) echo " c value 3";shift 2;;
cval4) echo " c value 4";shift 2;;
*) shift; echo " unknow c value";
if [ $#-eq0 ];then
exit0;
fi
shift;;
esac;;
*) echo " unknow prop $1";shift;;
esac
done
上⾯,在case 判断-b 后⾯的值时,再不确定-b后⾯⼀定有值,不能直接shift 2⽽是需要先进⾏⼀次判读
但按照Linus的风格,对于⼀多个单⼀属性可以连起来写,如对于xxx.sh -a -b -c可以写成xxx.sh -abc
若按照上⾯这种写法,要处理还得写好⼏个case,因此轮到重要的⼀个函数getopt登场
使⽤getopt辅助参数的解析
getopt不是标准的unix命令,但它在⼤多数的发⾏版中都会带有,getopt虽然是带个get但此函数其实主要不是获取⽽是规范
getopt后⾯接受-o选项表⽰程序可接受的短选项 如-o ab:c::,表⽰程序参数后⾯可接受的选项为-a -b -c 其中-a后⾯不接受参数,-b后⾯必须接受参数(:),-c后⾯参数可选(::)
getopt后⾯接受--long选项表⽰程序可接受的短选项 如--long along,blong:,clong::,长选项⽤逗号分隔开,后⾯接参数的标记号和短选项⼀致 getopt后⾯ -n选项为解析错误时提⽰的脚本名字
在对参数进⾏解析前先通过getopt进⾏解析
ARGS=`getopt -o ab:c: --long along,blong:,clong: -- "$@"`
#判断是否执⾏成功,没执⾏成功退出
if [ $? != 0 ] ; then echo "" >&2 ; exit1 ; fi
#重新设置参数
eval set -- "$ARGS"
通过getopt重新解析过的参数会更好解析,如对-a -b -c合起来写成-abc也可以解析,如下⾯xxx.sh
ARGS=`getopt -o abc -- "$@"`
if [ $? != 0 ] ; then echo "" >&2 ; exit1 ; fi
eval set -- "$ARGS"
while true;do
case"$1"in
-
a)
echo "a"
shift;;
-b)
echo "b"
shift;;
-c)
echo "c"shell代码
shift;;
--)
echo "--"
shift
break
;;
*)
echo "??"
shift
;;
esac
done
执⾏:
xxx.sh -abc
输出:
a
b
c
--
输⼊xxx.sh -cab或xxx.sh -bac都可以,若不使⽤getopt就需要借助正则来判断这种多样化的组合了使⽤getopt还有个好处,可以检测⼀些异常输⼊,如上例⼦输⼊xxx.sh -g会输出:getopt:⽆效选项--g
⼀个完整的例⼦example.sh:
fun_do_a_property()
{
echo "a($1)"
}
fun_do_b_property()
{
echo "b($1)"
}
ARGS=`getopt -o hva:b: --long help,version,along:,blong: -- "$@"`
if [ $? != 0 ] ; then echo "" >&2 ; exit1 ; fi
eval set -- "$ARGS"
while true;do
case"$1"in
-a|--along)
echo "-a | --along"
fun_do_a_property $2
shift 2
;;
-b|--blong)
echo "-b | --blong"
fun_do_b_property $2
shift 2
;;
-v|--version)
echo "-v | --version"
shift
;
;
-h|--help)
echo "-h | --help"
shift
;;
--)
shift
break
;;
*)
echo "未知的属性:{$1}"
exit1
;;
esac
done
执⾏example.sh -a 123 -b 456
-a | --along
a(123)
-b | --blong
b(456)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论