0%

shell脚本的命令行选项解析


标准UNIX命一般都提供大量的选项和参数,例如:

ps --help
Usage:
ps [options]

Try 'ps --help <simple|list|output|threads|misc|all>'
or 'ps --help <s|l|o|t|m|a>'
for additional help text.

在这些工具的命令行处理中使用了C函数getopt
shell脚本可以通过使用getopts来保持与UNIX一致的风格。

常用shell参数变量

  • $0 :即命令本身,相当于C/C++中的argv[0]
  • $1 :第一个参数.
  • $2, $3, $4 … :第2、3、4个参数,依次类推。
  • $# 参数的个数,不包括命令本身
  • $@ :参数本身的列表,也不包括命令本身
  • $* :和$@相同,但”$*“ 和 “$@”(加引号)并不同,”$*“将所有的参数解释成一个字符串,而”$@”是一个参数数组。

getopts

getopts有两个参数,
第一个参数是一个字符串,包括字符和“:”,每一个字符都是一个有效的选项,
如果字符后面带有“:”,表示这个字符有自己的参数。
如果字符串最前面带有“:”,表示开启静默模式,屏蔽系统提示错误。
getopts从命令中获取这些参数,并且删去了“-”,
并将其赋值在第二个参数中,如果带有自己参数,这个参数赋值在“OPTARG”中。

在使用getopts命令的时候,shell会自动产生两个变量OPTIND和OPTARG。
OPTIND初始值为1,其含义是下一个待处理的参数的索引。
只要存在,getopts命令返回true,所以一般getopts命令使用while循环;
OPTARG是当getopts获取到其期望的参数后存入的位置。

脚本

[ $# -eq 0   ] && usage

# option_string以冒号开头表示屏蔽脚本的系统提示错误,自己处理错误提示。
# 后面接合法的单字母选项,选项后若有冒号,则表示该选项必须接具体的参数

while getopts :s:t:i:oh OPTION
do
    case $OPTION in
        s)
            STRING=$OPTARG
            ;;

        t)
            STRING=`cat $OPTARG`
            ;;

        i)
            IN=$OPTARG        #$OPTARG为特殊变量,表示选项的具体参数
            ;;

        o)
            OUT=$OPTARG        #$OPTARG为特殊变量,表示选项的具体参数
            ;;

        h)
            echo "\033[31mHelp Info:\033[0m"
            java -jar sfntly-builds/java-openjdk-8/sfnttool/sfnttool.jar -h
            exit 1
        ;;

        \?)                       #如果出现错误,则解析为?
            usage
            ;;
    esac
done

#$OPTIND表示第几个选项,初始值为1
#shift $(($OPTIND - 1))
#if [ $# -eq 0  ]; then
#    usage
#fi

shift

使用shift $(($OPTIND-1))的作用是:
通过shift $(($OPTIND - 1))的处理,$*中就只保留了除去选项内容的参数,可以在其后进行正常的shell编程处理,例如:

./xx -i in -o out para1 para2 ...

经过处理之后,$*为 para1 para2,方便后续脚本处理

while getopts s:h OPTION
do
    case $OPTION in
        s)
            STRING=$OPTARG
            ;;

        h)
            echo "\033[31mHelp Info:\033[0m"
            exit 1
        ;;

        \?)                       #如果出现错误,则解析为?
            usage
            ;;
    esac
done

echo "OPTIND:"$OPTIND
shift $(($OPTIND - 1))      #除了选项之外,该脚本必须接至少一个参数

echo $0
echo $*
echo $@

if [ $# -eq 0  ]; then
    usage
fi

for file in $@          #依次处理剩余的参数
do
    echo $file
done

执行结果如下:

➜  /data/OpenSourceCode/subset-ttf  > ./test.sh -s "123" test1 test2 test3
OPTIND:3
./test.sh               $0
test1 test2 test3       $*
test1 test2 test3       $@
test1                   file
test2
test3