shell编程——getopt设计实例

使用getopt设计shell脚本选项示例

这里提供一个和seq命令功能相同的脚本seq.sh,然后设计这个脚本的选项。

先看一下seq命令的各个选项说明:

seq [OPTION]... LAST                  # 语法1
seq [OPTION]... FIRST LAST            # 语法2
seq [OPTION]... FIRST INCREMENT LAST  # 语法3

选项:
-s, --separator=STRING
使用指定的STRING分隔各数值,默认值为"\n"u

-w, --equal-width
使用0填充在前缀使所有数值长度相同

--help
显示帮助信息并退出

--version
输出版本信息并退出

以下是脚本内容:和seq相比,只有两个问题:第一个起点数值FIRST不能为负数;不支持小数功能。其它功能完全相同

#!/usr/bin/env bash
usage(){
cat <<'EOF'
Usage: $0 [OPTION]... LAST
  or:  $0 [OPTION]... FIRST LAST
  or:  $0 [OPTION]... FIRST INCREMENT LAST
EOF
}

# getopt的版本是增强版吗
getopt -T &>/dev/null;[ $? -ne 4 ] && { echo "not enhanced version";exit 1; }

# 参数解析
parameters=`getopt -o +s:w --long separator:,equal-width,help,version -n "$0" -- "$@"`
[ $? -ne 0 ] && { echo "Try '$0 --help' for more information."; exit 1; }

eval set -- "$parameters"

while true;do
    case "$1" in
        -w|--equal-width) ZERO_PAD="true"; shift ;;
        -s|--separator) SEPARATOR=$2; shift 2 ;;
        --version) echo "$0 version V1.0"; exit ;;
        --help) usage;exit ;;
        --)
            shift
            FIRST=$1
            INCREMENT=$2
            LAST=$3
            break ;;
        *) usage;exit 1;;
    esac
done


# 用于生成序列数
function seq_func(){

    # 是否要使用printf填充0位?
    [ "x$1" = "xtrue" ] && zero_pad="true" && shift
    
    # 设置first、step、last
    if [ $# -eq 1 ];then
        first=1
        step=1
        last=$1
    elif [ $# -eq 2 ];then
        first=$1
        step=1
        last=$2
    elif [ $# -eq 3 ]; then
        first=$1
        step=$2
        last=$3
    else
        echo "$FUNCNAME: ARGS wrong..."
        exit 1
    fi
    
    # 最后一个要输出的元素及其长度,决定要填充多少个0
    last_output=$[ last - ( last-first ) % step ]
    zero_pad_len=`[ ${#last_output} -gt ${#first} ] && echo ${#last_output} || echo ${#first}`

    # 生成序列数
    if [ "x$zero_pad" = "xtrue" ];then
        # 填充0
        if [ $step -gt 0 ];then
            # 递增,填充0
            for((i=$first;i<=$last;i+=$step)){
                [ $last_output -eq $i ] && { printf "%0${zero_pad_len}i\n" "$i";return; }
                printf "%0${zero_pad_len}i " $i
            }
        else
            # 递减,填充0
            for((i=$first;i>=$last;i+=$step)){
                [ $last_output -eq $i ] && { printf "%0${zero_pad_len}i\n" "$i";return; }
                printf "%0${zero_pad_len}i " $i
            }
        fi
    else
        # 不填充0
        if [ $step -gt 0 ];then
            # 递增,不填充0
            for((i=$first;i<=$last;i+=$step)){
                [ $last_output -eq $i ] && { printf "%i\n" "$i";return; }
                printf "%i " $i
            }
        else
            # 递减,不填充0
            for((i=$first;i>=$last;i+=$step)){
                [ $last_output -eq $i ] && { printf "%i\n" "$i";return; }
                printf "%i " $i
            }
        fi
    fi
}

# 指定输出分隔符
: ${SEPARATOR="\n"}

# 输出结果
seq_func $ZERO_PAD $SEPARATOR $FIRST $INCREMENT $LAST | tr " " "$SEPARATOR"

上面解析选项的脚本缺陷在于无法解析FIRST为负数的情况,例如./seq.sh -w -5 3将报错。但可以写为标准的./seq.sh -w -- -5 -3语法。

你可能感兴趣的:(shell编程——getopt设计实例)