使用嵌套的 case 语句解析参数

使用嵌套的 case 语句解析参数

我正在尝试构建一个具有两种模式的程序,每种模式都采用一组不同的参数。我尝试实现嵌套的 case 语句,如 @geekosaur 中所述这里,通过case "$1"模式和case "$2"论证。

我有一个--help描述可用模式的程序的通用选项,以及--help描述参数的每种模式的单独选项。

如果我运行:

./program.sh --help作品

./program.sh mode1 --help作品

./program.sh mode1 --unknown有效(它正确捕获未知选项并调用模式1的使用函数)

然而:

./program.sh mode1 --option1 file

ERROR: unknown parameter file

即,它将“file”识别为参数,而不是键“option1”的值。

我怎样才能做到这一点?我是否搞乱了我的“班次”,或者我是否需要嵌套循环?

(为了简单起见,下面的代码中仅显示“mode1”)

#!/bin/bash

usage_general() {
    echo "Usage: ProgramName [modes]"
    echo ""
    printf "%-10s %s\n" "mode1" "Run subprogram 1."
    printf "%-10s %s\n" "mode2" "Run subprogram 2."
}

usage_mode1() {
    echo "Usage: ProgramName mode1 [options]"
    echo ""
    printf "%-10s %s\n" "-1 | --option1" "Arg 1 for mode1"
    printf "%-10s %s\n" "-2 | --option2" "Arg 2 for mode1."
}


while [[ $# -gt 0 ]]
do
    case "$1" in
    -h | --help)
        usage_general
        exit
        ;;

    mode1)

        case "$2" in
        -h | --help)
            usage_mode1
            exit
            ;;
        -1 | --option1)
            val1="$3"
            shift 2
            ;;
        -2 | --option2)
            val2="$3"
            shift 2
            ;;
        *)
            echo "ERROR: unknown parameter $2"
            usage_mode1
            exit 1
            ;;
        esac
        ;;

    *)
        echo "ERROR: unknown parameter $1"
        usage_general
        exit 1
        ;;
    esac
done

答案1

当您shift 2在内部使用时case,您会移走$1$2,但不会移走$3文件名。

您需要执行一个单独的循环来解析mode1andmode2子命令的选项。

假设当在脚本的命令行参数中找到子命令时,其余选项和选项参数属于该子命令,您可以像这样分割解析:

run_mode1 () {
    while [ "$#" -gt 0 ]; do
        case "$1" in
        -h | --help)
            usage_mode1
            exit
            ;;
        -1 | --option1)
            val1="$2"
            shift 2
            ;;
        -2 | --option2)
            val2="$2"
            shift 2
            ;;
        *)
            echo "ERROR: unknown parameter $1"
            usage_mode1
            exit 1
            ;;
        esac
    done

    # code for actually running mode1 goes here
}

while [[ $# -gt 0 ]]
do
    case "$1" in
    -h | --help)
        usage_general
        exit
        ;;

    mode1)
        shift
        run_mode1 "$@"
        break
        ;;

    *)
        echo "ERROR: unknown parameter $1"
        usage_general
        exit 1
        ;;
    esac
done

在这里,一旦遇到mode1命令行参数,我们就运行 shell 函数。该函数负责解析参数列表的其余部分。

显然,这仅在特定情况下才有效全部选项剧本(不是子命令)发生命令行上的任何给定子命令,并且在脚本的任何一次调用中只能有一个带有选项的子命令。

以脚本能够同时接受两个或多个带选项的子命令的方式实现命令行解析并非不可能,如下所示

./script.sh ...options... mode1 ...options... mode2 ...options...

但我暂时先不谈这个。

相关内容