1

我的脚本使用的参数是我的两倍:

第一次使用以下代码,以确保没有我不想要的参数(我只考虑 arg1:arg2:arg3)

     PARAM=$@
     while [ "$#" -gt "0" ]; do
              case $1 in
                       arg1)
                                shift2
                                ;;
                       arg2)
                                shift
                                ;;
                       arg3)
                                shift
                                ;;
                       *)
                                echo "Usage : ./test.sh arg1 <VAL1> <VAL2> [arg2] [arg3]"
                                exit 2
                                ;;
              esac
              shift
     done

我想重新解析这些参数,并能够在我得到 arg1 时得到以下两个参数,所以我从这样的事情开始:

     for command in $PARAM
     do
         case $command in
             arg1)
                 shift
                 VALUE1=$command
                 shift
                 VALUE2=$command
                 exec_arg1
                 ;;
         esac
         shift

但是在使用“shift”时,我得到了错误shift: can't shift that many

shebang 是“#!/bin/sh”,我正在寻找一个无需使用 bash 的 shebang 的解决方案(即“#!/bin/bash”)

4

1 回答 1

2

您不能将列表连接到字符串并安全地将其转回列表(没有复杂的辅助函数)。请参阅此常见问题解答

shift在不同的 shell 中表现不同。在 Bash 和 Zsh 中,当没有保留位置参数时,shift只返回 false。包括 Dash 在内的许多 shell(与 POSIX 相反,可能是因为 ksh 行为)反而会引发致命错误。ksh93 通过内置提供了一种解决此问题的方法command,但这似乎也不是由 POSIX 指定的,尽管这个 workaroud 无论如何也适用于 Dash,但不是mksh(我昨天刚刚发现的 mksh 中还有一个错误阻止它工作,并且维护者可能不会以允许解决方法的方式修复它)。Busybox 也不遵循 POSIX,也没有给出有意义的退出代码。

无论如何,关键是您不能依赖,shift因为这里有很多 shell 有错误。如果可能的话,您应该迭代参数而不移动它们,并以确保您不会像当前那样移动到边缘的方式测试剩余参数的数量。我认为您预先验证参数的想法并不比同时验证和解析更好。

#!/bin/sh

f()
    if ! ${_called_f+false}; then
        while ! ${1+false}; do
            case $1 in
                arg1)
                    ${3+:} return 1
                    value1=$2 value2=$3
                    shift 3
                    exec_arg1
                    ;;
                arg[23])
                    ${2+:} return 1
                    value1=$1
                    shift
                    "exec_arg${value1##"${value1%?}"}" # Only do this crap if restricted to POSIX
                    ;;
                *)
                    return 1
            esac
        done
    else
        # Hack nobody will understand since this probably isn't what you want anyway.
        _called_f= value1= value2= command eval \
            'typeset +x value{1,2} 2>/dev/null; f "$@"'
    fi

if ! f "$@"; then
    echo 'Error parsing args, exiting...' >&2
    exit 1
fi

参见:选项解析

于 2013-01-07T13:16:31.870 回答