Shell 获取参数的方式
写shell脚本的时候,往往需要从外部获取参数,例如:
$ sh demo.sh a
那么如何将上面的参数a传到shell程序里面呢。
最常用的是,$0 $1... $10,这些位置变量 其中$0是shell程序的名字,$1,$2...分别为第一个参数,第二个参数... 我们demo.sh 如下所示:
$ cat demo.sh
#! /bin/bash
cat << EOF
Usage: sh $0 $1
EOF
$ sh demo.sh a
Usage: sh demo.sh a
$开头的参数有:
$0: 程序的名字
$#: 变量的个数
$@:所有的变量,即:$1...$最后,不包括程序的名字
这有一个问题,当参数很多的时候,别人用你的程序时,交互性不是很好,别人还得记住脚本每一个参数的位置和作用,会很麻烦。这时可以加提示符:例如
$ sh demo.sh -a A -b B -c C
那这个怎么实现呢? 实现的方式有两种 利用shift
和getopts
$ cat demo.sh
#! /bin/bash
while [ $# -gt 0 ];
do
case $1 in
-a) echo "-a----$2"
shift
;;
-b) echo "-b----$2"
shift
;;
-c) echo "-c----$2"
shift
;;
esac
shift
done
$ sh demo.sh -a A -b B -c C
-a----A
-b----B
-c----C
getopts
函数则简化上面的选项处理过程。我们下面来看看它的使用方法。
函数的第一个参数:合法选项字母的一个字符串, 如果字母后面后·:
则表示必须要提供参数,这时getopts
函数会将参数放到OPTARG
中,另外一个变量是OPTIND
代表下一个待处理参数的索引值。
函数的第二个参数:变量名称,每次getopts
被调用的时候,都会被更新,这个变量名字是没有限制的。getopts
在找不到合法的选项的时候会将这个变量设置为一个问号。具体的实现如下所示:
#! /bin/bash
while getopts a:b:c: opt;
do
case $opt in
a) echo "-a ---- $OPTARG"
;;
b) echo "-b ---- $OPTARG"
;;
c) echo "-c ---- $OPTARG"
;;
?) echo "$opt is an invalid option"
;;
esac
done
$ sh demo.sh -a A -b B -c C -d
-a ---- A
-b ---- B
-c ---- C
demo.sh: illegal option -- d --getopts输出的错误信息
? is an invalid option --脚本判断输出的错误信息,这里将-d option设置为了?
但是getopts并不能处理长选项,这时可以借助getopt
,大家可以man
一下:
NAME
getopt - parse command options (enhanced)
从基本解释可以看出,它是一个加强版的getopts
,虽然getopts
比它还多了一个s,但是论功力,还是远远不如getopt
。这里有一个官网的例子:http://software.frodo.looijaard.name/getopt/docs/getopt-parse.bash。为了保持队形,稍微改写成解析-a -b -c --apple --banana --cat的demo.
$ cat demo_getopt.sh
#! /bin/bash
TEMP=$(getopt -o ab:c:: --long apple,banana:,cat:: -- "$@")
if [ "$?" != "0" ]; then
echo "Terminating..." >&2;
exit 1
fi
eval set -- "$TEMP" 用"$TEMP"参数--前的字符串重置$1.$2.$3.$4...
echo $TEMP
while true; do 解析$1.$2.$3.$4...
case "$1" in
-a|--apple) echo "Option $1, no argument"; shift 2;;
-b|--banana) echo "Option $1 --> $2"; shift 2;;
-c|--cat)
case "$2" in
"") echo "Option $1, no argument"; shift 2;;
*) echo "Option $1 --> $2"; shift 2;;
esac ;;
"--") shift; break;;
*) echo "Internal error!"; exit 1;;
esac
done
echo "Remaining arguments:"
for arg in $@; do
echo '-->' "$arg"
done
其中
option ,表示后面不能跟参数
option:,表示后面必须接参数
option::,表示后面可接可不接
运行结果
$ sh demo_getopt.sh -a -b B -cC --apple --banana B testa testb
-a -b 'B' -c 'C' --apple --banana 'B' -- 'testa' 'testb' 这是getopt解析的结果
Option -a, no argument
Option -b --> B
Option -c --> C
Option --apple, no argument
Option --banana --> B
Remaining arguments:
--> testa
--> testb