将 $@ 分配给 shell 函数中的另一个变量

I.A*_*Guy 3 bash zsh array shell-script

我正在制作一个gc可以区分 git commit/checkout的智能别名。

如果gc在不带任何参数或带有-a,-m参数的情况下调用,则运行 git commit。否则,运行 git checkout(如果有一个b带有附加参数的标志)。如果调用 gc 的任何其他变体,我宁愿它抛出错误而不是做一些意想不到的事情。

到目前为止,这是我的 shell 函数。

gc() {
    args=$@
    commit=false
    checkout=false

    # Check flags
    while getopts ":am:b" opt; do
        case $opt in
            a|m)
                commit=true
                ;;
            b)
                checkout=true
                ;;
            \?)
                echo "Unknown flags passed."
                return 1
                ;;
        esac
    done

    shift "$((OPTIND-1))"

    # Check number of arguments
    if [[ "$#" == 0 ]]; then
        commit=true
    elif [[ "$#" == 1 ]]; then
        checkout=true
    else
        echo "Too many arguments"
        return 1
    fi

    # Finally run respective command
    if [[ $commit == true && $checkout == true ]]; then
        echo "Unable to ascertain which operation you would like to perform."
        return 1
    elif [[ $commit == true ]]; then
        git commit "$args"
    elif [[ $checkout == true ]]; then
        git checkout "$args"
    else
        echo "Undefined behavior"
        return 1
    fi
}
Run Code Online (Sandbox Code Playgroud)

但是,这不能正常工作。经过一些试验,我发现分配$@给另一个变量是根本原因,但我无法理解为什么以及究竟出了什么问题。

另外,当我第一次编写 shell 函数时,请突出显示我所犯的任何错误。

jes*_*e_b 7

$@ 是一个数组,将其分配给一个数组:

args=("$@")
Run Code Online (Sandbox Code Playgroud)

然后将其用作数组:

elif [[ $commit == true ]]; then
    git commit "${args[@]}"
elif [[ $checkout == true ]]; then
    git checkout "${args[@]}"
else
Run Code Online (Sandbox Code Playgroud)

当前代码中发生的情况是所有单独的参数都存储为单个字符串。所以如果你打电话:

bc -a "foo bar"
Run Code Online (Sandbox Code Playgroud)

这被分配args为:

args='-a foo bar'
Run Code Online (Sandbox Code Playgroud)

然后而不是执行:

git commit -a "foo bar"
Run Code Online (Sandbox Code Playgroud)

你得到:

git commit '-a foo bar'
Run Code Online (Sandbox Code Playgroud)