【问题标题】:Using positional parameters in place of if statements使用位置参数代替 if 语句
【发布时间】:2017-05-02 06:42:31
【问题描述】:

我试图更好地理解如何使用位置参数作为脚本的参数来编写 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 语句的情况下,将其编写为采用 有效使用 中显示的相同参数?

我没有要求任何人重写我的脚本。我只是在寻找一些指导,以更好地了解如何正确执行此操作。

【问题讨论】:

  • 您是否尝试过考虑getopts 来满足您的要求?它是为此量身定做的
  • 感谢您的详细研究,但仍不清楚您想要做什么?您能否提供我们测试所需的最小输入和输出?
  • 你认为我应该缩短问题?
  • 不完全是缩短它,但让人们更容易理解你正在寻找的代码。例如我想这样做,这样等等。
  • 或者给我们一个你想要实现的所有可能的命令行输入的列表

标签: bash shell parameters


【解决方案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

【讨论】:

  • 哇,这确实简化了事情。谢谢你。 :)
猜你喜欢
  • 2014-06-05
  • 2018-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
相关资源
最近更新 更多