有没有办法避免bash中的位置参数? [英] Is there a way to avoid positional arguments in bash?

查看:89
本文介绍了有没有办法避免bash中的位置参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须用bash编写一个函数.该函数将接受约7个参数.我知道我可以调用这样的函数:

I have to write a function in bash. The function will take about 7 arguments. I know that I can call a function like this:

要调用带有参数的函数:

To call a function with parameters:

function_name $arg1 $arg2

我可以在函数中引用这样的参数:

And I can refer my parameters like this inside the function:

function_name () {
   echo "Parameter #1 is $1"
}

我的问题是,是否有更好的方法引用函数内部的参数?我可以避免使用$ 1,$ 2,$ 3等吗,而只需使用$ arg1,$ arg2等吗?

My question is, is there a better way refer to the parameters inside the function? Can I avoid the $1, $2, $3, .... thing and simply use the $arg1, $arg2, ...?

是否有合适的方法来执行此操作,或者我需要将这些参数重新分配给函数中的其他一些变量?例如:

Is there a proper method for this or do I need to re-assign these parameters to some other variables inside the function? E.g.:

function_name () {
   $ARG1=$1
   echo "Parameter #1 is $ARG1"
}

任何例子都将不胜感激.

Any example would be much appreciated.

推荐答案

通常的做法是将参数分配给函数中的局部变量,即:

The common way of doing that is assigning the arguments to local variables in the function, i.e.:

copy() {
    local from=${1}
    local to=${2}

    # ...
}


另一种解决方案可能是 getopt 样式的选项解析.


Another solution may be getopt-style option parsing.

copy() {
    local arg from to
    while getopts 'f:t:' arg
    do
        case ${arg} in
            f) from=${OPTARG};;
            t) to=${OPTARG};;
            *) return 1 # illegal option
        esac
    done
}

copy -f /tmp/a -t /tmp/b


遗憾的是,bash无法处理更具可读性的长选项,即:


Sadly, bash can't handle long options which would be more readable, i.e.:

copy --from /tmp/a --to /tmp/b

为此,您需要使用外部getopt程序(我认为该程序仅在GNU系统上具有长选项支持)或手动实现长选项解析器,即:

For that, you either need to use the external getopt program (which I think has long option support only on GNU systems) or implement the long option parser by hand, i.e.:

copy() {
    local from to

    while [[ ${1} ]]; do
        case "${1}" in
            --from)
                from=${2}
                shift
                ;;
            --to)
                to=${2}
                shift
                ;;
            *)
                echo "Unknown parameter: ${1}" >&2
                return 1
        esac

        if ! shift; then
            echo 'Missing parameter argument.' >&2
            return 1
        fi
    done
}

copy --from /tmp/a --to /tmp/b

另请参阅:您也可以偷懒,只需将变量"作为参数传递给函数,即:

You can also be lazy, and just pass the 'variables' as arguments to the function, i.e.:

copy() {
    local "${@}"

    # ...
}

copy from=/tmp/a to=/tmp/b

,您将在函数中使用${from}${to}作为局部变量.

and you'll have ${from} and ${to} in the function as local variables.

请注意,存在与以下相同的问题-如果未传递特定变量,则它将从父环境继承.您可能要添加安全线",例如:

Just note that the same issue as below applies — if a particular variable is not passed, it will be inherited from parent environment. You may want to add a 'safety line' like:

copy() {
    local from to    # reset first
    local "${@}"

    # ...
}

确保未通过时未设置${from}${to}.

to ensure that ${from} and ${to} will be unset when not passed.

如果您很感兴趣非常糟糕的,则在调用该函数时也可以将参数分配为全局变量,即:

And if something very bad is of your interest, you could also assign the arguments as global variables when invoking the function, i.e.:

from=/tmp/a to=/tmp/b copy

然后您可以在copy()函数中使用${from}${to}.请注意,然后您应该始终传递所有参数.否则,随机变量可能会泄漏到函数中.

Then you could just use ${from} and ${to} within the copy() function. Just note that you should then always pass all parameters. Otherwise, a random variable may leak into the function.

from= to=/tmp/b copy   # safe
to=/tmp/b copy         # unsafe: ${from} may be declared elsewhere


如果您具有bash 4.1(我认为),则还可以尝试使用关联数组.它将允许您传递命名参数,但是 很难看.像这样:


If you have bash 4.1 (I think), you can also try using associative arrays. It will allow you to pass named arguments but it will be ugly. Something like:

args=( [from]=/tmp/a [to]=/tmp/b )
copy args

然后在copy()中,您需要 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆