shell命令行参数解析工具:getopts

半兽人 发表于: 2018-11-19   最后更新时间: 2018-11-19 16:30:02  
{{totalSubscript}} 订阅, 4,131 游览

在shell脚本中,对于简单的参数,我们使用$1 $2来处理即可,如下:

#!/bin/bash

SOFT_DIR=$1
MAVEN_DIR=$2
echo $SOFT_DIR
echo $MAVEN_DIR

-----------------

$ sh test.sh /home/soft /home/soft/maven
/home/soft
/home/soft/maven

但是,如果你的脚本参数非常多,那使用上面的这种方式就非常不合适,你无法清楚地记得每个位置对应的是什么参数。所以,我们可以使用bash内置的getopts,下面是一个简单的例子:

#!/bin/bash

usage() {
    echo "Usage:"
    echo "  test.sh [-j JAVA_DIR] [-m MAVEN_DIR]"
    echo "Description:"
    echo "    JAVA_DIR, the path of java."
    echo "    MAVEN_DIR, the path of maven."
    exit -1
}

upload="false"

while getopts 'h:j:m:u' OPT; do
    case $OPT in
        j) JAVA_DIR="$OPTARG";;
        m) MAVEN_DIR="$OPTARG";;
        u) upload="true";;
        h) usage;;
        ?) usage;;
    esac
done

echo $JAVA_DIR
echo $MAVEN_DIR
echo $upload

---------------------------

$ sh test.sh -j /home/soft/java -m /home/soft/maven
/home/soft/java
/home/soft/maven
false

$ sh test.sh -j /home/soft/java -m /home/soft/maven -u
/home/soft/java
/home/soft/maven
true

$ sh test.sh -h   
test.sh: option requires an argument -- h
Usage:
  test.sh [-j JAVA_DIR] [-m MAVEN_DIR]
Description:
    JAVA_DIR, the path of java.
    MAVEN_DIR, the path of maven.

getopts后面跟的字符串就是参数列表,每个字母代表一个选项,如果字母后面跟一个就表示这个选项还会有一个值,比如上面例子中对应的-j /home/soft/java-m /home/soft/maven。而getopts字符串中没有跟随:的字母就是开关型选项,不需要指定值,等同于true/false,只要带上了这个参数就是true

getopts识别出各个选项之后,就可以配合case进行操作。操作中,有两个"常量",一个是OPTARG,用来获取当前选项的值;另外一个就是OPTIND,表示当前选项在参数列表中的位移。case的最后一项是?,用来识别非法的选项,进行相应的操作,我们的脚本中输出了帮助信息。

当选项参数识别完成以后,我们就能识别剩余的参数了,我们可以使用shift进行位移,抹去选项参数。

#!/bin/bash

usage() {
    echo "Usage:"
    echo "  test.sh [-j JAVA_DIR] [-m MAVEN_DIR]"
    echo "Description:"
    echo "    JAVA_DIR, the path of java."
    echo "    MAVEN_DIR, the path of maven."
    exit -1
}

upload="false"

echo $OPTIND

while getopts 'j:m:u' OPT; do
    case $OPT in
        j) JAVA_DIR="$OPTARG";;
        m) MAVEN_DIR="$OPTARG";;
        u) upload="true";;
        h) usage;;
        ?) usage;;
    esac
done

echo $OPTIND
shift $(($OPTIND - 1))
echo $1

---------------
$ sh test.sh -j /home/soft/java -m /home/soft/maven otherargs
1
5
otherargs

sh test.sh -j /home/soft/java -m /home/soft/maven -u otherargs
1
6
otherargs

在上面的脚本中,我们位移的长度等于case循环结束后的OPTIND - 1OPTIND的初始值为1,当选项参数处理结束后,其指向剩余参数的第一个。getopts在处理参数时,处理带值的选项参数,OPTIND2;处理开关型变量时,OPTIND则加1。

以上就是对getopts的简单介绍。

在放一个复杂一点的例子:

optspec=":hv-:"
while getopts "$optspec" optchar; do

    case "${optchar}" in
        -)
            case "${OPTARG}" in
                servers=*)
                    SERVERS=${OPTARG##*=}
                    ;;
                data_dir=*)
                    DATA_DIR=${OPTARG##*=}
                    ;;
                data_log_dir=*)
                    DATA_LOG_DIR=${OPTARG##*=}
                    ;;
                log_dir=*)
                    LOG_DIR=${OPTARG##*=}
                    ;;
                conf_dir=*)
                    CONF_DIR=${OPTARG##*=}
                    ;;
                client_port=*)
                    CLIENT_PORT=${OPTARG##*=}
                    ;;
                election_port=*)
                    ELECTION_PORT=${OPTARG##*=}
                    ;;
                server_port=*)
                    SERVER_PORT=${OPTARG##*=}
                    ;;
                tick_time=*)
                    TICK_TIME=${OPTARG##*=}
                    ;;
                init_limit=*)
                    INIT_LIMIT=${OPTARG##*=}
                    ;;
                sync_limit=*)
                    SYNC_LIMIT=${OPTARG##*=}
                    ;;
                heap=*)
                    HEAP=${OPTARG##*=}
                    ;;
                max_client_cnxns=*)
                    MAX_CLIENT_CNXNS=${OPTARG##*=}
                    ;;
                snap_retain_count=*)
                    SNAP_RETAIN_COUNT=${OPTARG##*=}
                    ;;
                purge_interval=*)
                    PURGE_INTERVAL=${OPTARG##*=}
                    ;;
                max_session_timeout=*)
                    MAX_SESSION_TIMEOUT=${OPTARG##*=}
                    ;;
                min_session_timeout=*)
                    MIN_SESSION_TIMEOUT=${OPTARG##*=}
                    ;;
                log_level=*)
                    LOG_LEVEL=${OPTARG##*=}
                    ;;
                *)
                    echo "Unknown option --${OPTARG}" >&2
                    exit 1
                    ;;
            esac;;
        h)
            print_usage
            exit
            ;;
        v)
            echo "Parsing option: '-${optchar}'" >&2
            ;;
        *)
            if [ "$OPTERR" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
                echo "Non-option argument: '-${OPTARG}'" >&2
            fi
            ;;
    esac
done

调用:

- sh 
        - -c
        - "start-zookeeper \
          --servers=3 \
          --data_dir=/var/lib/zookeeper/data \
          --data_log_dir=/var/lib/zookeeper/data/log \
          --conf_dir=/opt/zookeeper/conf \
          --client_port=2181 \
          --election_port=3888 \
          --server_port=2888 \
          --tick_time=2000 \
          --init_limit=10 \
          --sync_limit=5 \
          --heap=512M \
          --max_client_cnxns=60 \
          --snap_retain_count=3 \
          --purge_interval=12 \
          --max_session_timeout=40000 \
          --min_session_timeout=4000 \
          --log_level=INFO"
更新于 2018-11-19

查看shell更多相关的文章或提一个关于shell的问题,也可以与我们一起分享文章