Sh - 获取下一个数组元素

时间:2013-01-07 11:40:21

标签: linux bash shell sh

我得到了两次与我的脚本一起使用的参数:

第一次使用以下代码,以确保没有我不想要的参数(我只考虑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:无法移动那么多

shebang是“#!/ bin / sh”,我正在寻找解决方案,而不必使用bash的shebang(即“#!/ bin / bash”)

1 个答案:

答案 0 :(得分:2)

您无法将列表连接到字符串并安全地将其重新转换为列表(没有complex helper function)。请参阅this FAQ

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

无论如何,关键是你不能依赖shift,因为这里有很多炮弹都有虫子。如果可能的话,你应该迭代参数而不移动它们,并以一种确保你不像现在这样移动边缘的方式测试剩余参数的数量。我不认为你预先验证参数的想法比仅仅同时验证和解析更好。

#!/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

另请参阅:option parsing