使用位置参数代替if语句

时间:2017-05-02 06:42:31

标签: bash shell parameters

我试图更好地理解如何使用位置参数作为脚本的参数来编写bash脚本。具体来说,我想了解如何使脚本尽可能用户友好,能够处理来自任何位置的多个参数。其中很多ls -lstls -stl相同。我决定尝试密码生成器。我不太熟悉编写带参数的脚本。过了一会儿,我决定用if语句完成整个事情。

注意:要在信用到期时提供信用,下面脚本中的rand_string功能直接来自this answer

#!/bin/bash

## grep -v '##' will remove all the comments if you're so inclined :)
usage(){
echo "usage: $0 [n][-c]||[-h]"  
}

## Character set used to create random strings 
chars=( {a..z} {A..Z} {0..9} \! \" \# \$  \% \& \( \) \* \+ \, \- \. \/ \: \; \< \= \> \? \@ \[ \] \^ \_ \` \{ \| \} \~ \\ )

## Create random string from character set
rand_string() { 
    local c=$1 ret=
    while((c--)); do
        ret+=${chars[$((RANDOM%${#chars[@]}))]}; done
    printf '%s\n' "$ret"
}

## get a random number between 14-50
length() {
    python -S -c "import random; print random.randrange(14,50)"
}

## regular expression to test for valid numbers
re='^[0-9]+$'

## if no options specified 
## create a random string of charcters
## of a random length between 14-50 characters
## display password on screen and exit
if [ ! "$1" ]; then
    set - "$(length)"
    password="$(rand_string "$1")"
    echo "$password"
    exit
fi

## if option 1 or option 2 is -h or -help
## display usage and exit
if [[ "$1" == -h || "$1" == -help || "$2" == -h || "$2" == -help ]]; then
    usage
    exit
fi

## if more than 2 options
## exit with error code 1
if [[ $# -gt 2 ]]; then
    echo "Invalid number of options specified"
    usage
    exit 1
fi
## if exactly 2 options
if [[ $# -eq 2 ]]; then
    ## test if option 1 is a number
    ## if option 1 is NOT a number 
    if [[ ! "$1" =~ $re ]]; then
        ## test if option 1 is -c or -copy
        if [[ "$1" == -c || "$1" == -copy ]]; then
            ## if option 1 is -c or -copy
            ## test if option 2 is a number
            ## if 2 is a number and 1 is -c or -copy 
            ## execute the command
            if [[ "$2" =~ $re ]]; then
                set - "$(length)"
                rand_string "$1" | pbcopy
                echo "Password copied to clipboard"
                exit
            ## if option 1 is -c or -copy
            ## but option 2 is NOT a number
            ## exit script with error code 1
            elif [[ ! "$2" =~ $re ]]; then
                echo "Unrecognized option \"$2\""
                usage
                exit 1
            fi
        else
            echo "Unrecognized option \"$1\""
            exit 1
        fi
    ## if option 1 is a number
    elif [[ "$1" =~ $re ]]; then
        ## and option 2 is -c or -copy
        ## execute the command
        if [[ "$2" == -c || "$2" == -copy ]]; then
            rand_string "$1" | pbcopy
            echo "Password copied to clipboard"
            exit
        ## if option 1 is a number 
        ## but option 2 is not -c or -copy
        ## exit script with error code 1
        else
            echo "Unrecognized option \"$2\""
            usage
            exit 1
        fi
    fi
## if exactly one option specified
elif [[ $# -eq 1 ]]; then
    ## if option is NOT a number
    ## check if option is -c or -copy
    if [[ ! "$1" =~ $re ]]; then
        ## if option is -c or -copy
        ## execute the command 
        if [[ "$1" == -c || "$1" == -copy ]]; then
            set - "$(length)"
            rand_string "$1" | pbcopy
            echo "Password copied to clipboard"
            exit
        ## if option is neither a number nor -c or -copy
        ## exit script with error code 1
        else
            echo "Unrecognized option \"$1\""
            usage
            exit 1
        fi
    ## if option is a number
    ## execute the command
    elif [[ "$1" =~ $re ]]; then
        rand_string "$1"
    fi
fi

此脚本有两个可选参数:

  • 任何整数,例如.. 102954以确定字符串的长度

  • -c-copy将字符串复制到剪贴板

  • -h-help显示usage功能

可以从$1$2位置调用上述任何参数。任何这些参数也可以省略。

假设脚本名为password,则以下任何一种有效用途

password

password 25

password -c

password 16 -copy

password -c 42

password -help

但是脚本本身是if语句的一大堆。它冗长,凌乱,难以阅读。

所以我的问题是:如何在不使用这么多if语句的情况下编写有效用途中显示的相同参数?

我没有要求任何人重写我的剧本。我正在寻找一些指导,以便更好地理解如何正确地做到这一点。

1 个答案:

答案 0 :(得分:1)

如果您不想使用getopts,那么简单的方法就是shift个参数。

#!/bin/bash

usage(){
        echo "usage: $0 [n][-c]||[-h]" >&2
        exit 1
}

declare copy=
declare argument=

while [ "$1" ]; do
        case "$1" in
                -h|-help)
                        usage
                        ;;

                -c|-copy)
                        copy=1
                        ;;

                *)
                        [[ "$1" =~ ^[0-9]+$ ]] || usage
                        argument="$1"
                        ;;
        esac
        shift
done

[ "$argument" ] || argument=$(length)

if [ "$copy" ]; then
        rand_string "$argument" | pbcopy
else
        rand_string "$argument"
fi