【问题标题】:Multiple option arguments using getopts (bash)使用 getopts (bash) 的多个选项参数
【发布时间】:2013-04-17 16:10:07
【问题描述】:

我正在尝试在 bash 中使用 getopts 处理命令行参数。其中一项要求是处理任意数量的选项参数(不使用引号)。

第一个示例(仅获取第一个参数)

madcap:~/projects$ ./getoptz.sh -s a b c
-s was triggered
Argument: a

第二个例子(我希望它表现得像这样,但不需要引用参数”

madcap:~/projects$ ./getoptz.sh -s "a b c"
-s was triggered
Argument: a b c

有没有办法做到这一点?

这是我现在拥有的代码:

#!/bin/bash
while getopts ":s:" opt; do
    case $opt in
    s) echo "-s was triggered" >&2
       args="$OPTARG"
       echo "Argument: $args"
       ;;
   \?) echo "Invalid option: -$OPTARG" >&2
       ;;
    :) echo "Option -$OPTARG requires an argument." >&2
       exit 1
       ;;
    esac
done

【问题讨论】:

标签: linux bash shell unix getopts


【解决方案1】:

我认为您想要的是从单个选项中获取值列表。为此,您可以根据需要多次重复该选项,并将其参数添加到数组中。

#!/bin/bash

while getopts "m:" opt; do
    case $opt in
        m) multi+=("$OPTARG");;
        #...
    esac
done
shift $((OPTIND -1))

echo "The first value of the array 'multi' is '$multi'"
echo "The whole list of values is '${multi[@]}'"

echo "Or:"

for val in "${multi[@]}"; do
    echo " - $val"
done

输出将是:

$ /tmp/t
The first value of the array 'multi' is ''
The whole list of values is ''
Or:

$ /tmp/t -m "one arg with spaces"
The first value of the array 'multi' is 'one arg with spaces'
The whole list of values is 'one arg with spaces'
Or:
 - one arg with spaces

$ /tmp/t -m one -m "second argument" -m three
The first value of the array 'multi' is 'one'
The whole list of values is 'one second argument three'
Or:
 - one
 - second argument
 - three

【讨论】:

    【解决方案2】:

    您可以自己解析命令行参数,但不能将getopts 命令配置为识别单个选项的多个参数。 fedorqui's recommendation 是一个不错的选择。

    这是自己解析选项的一种方法:

    while [[ "$*" ]]; do
        if [[ $1 = "-s" ]]; then
            # -s takes three arguments
            args="$2 $3 $4"
            echo "-s got $args"
            shift 4
        fi
    done
    

    【讨论】:

    • 确实,“识别单个选项的多个参数”是不可能的,但可以重复该选项。我在答案中添加了一个示例,因为我认为这才是真正想要的。
    【解决方案3】:

    这是我使用用户定义函数执行此操作的方法:getopts-extra

    function getopts-extra () {
        declare i=1
        # if the next argument is not an option, then append it to array OPTARG
        while [[ ${OPTIND} -le $# && ${!OPTIND:0:1} != '-' ]]; do
            OPTARG[i]=${!OPTIND}
            let i++ OPTIND++
        done
    }
    
    # Use it within the context of `getopts`:
    while getopts s: opt; do
        case $opt in
           s) getopts-extra "$@"
              args=( "${OPTARG[@]}" )
        esac
    done
    

    getoptz.sh 的完整示例:

    #!/usr/bin/env bash
    
    function getopts-extra () {
        declare i=1
        # if the next argument is not an option, then append it to array OPTARG
        while [[ ${OPTIND} -le $# && ${!OPTIND:0:1} != '-' ]]; do
            OPTARG[i]=${!OPTIND}
            let i++ OPTIND++
        done
    }
    
    function main () {
        declare args
        declare OPTIND OPTARG opt
        while getopts :s: opt; do
            case $opt in
            s) getopts-extra "$@"
               args=( "${OPTARG[@]}" )
               ;;
           \?) echo "Invalid option: -$OPTARG" >&2
               ;;
            :) echo "Option -$OPTARG requires an argument." >&2
               exit 1
               ;;
            esac
       done
    
       declare i
       for i in "${!args[@]}"; do
           echo "args[$i]: ${args[i]}"
       done
    }
    
    main "$@"
    
    exit
    
    

    测试:

    bash getoptz.sh -s a b c
    

    输出:

    args[0]: a
    args[1]: b
    args[2]: c
    

    此函数是名为 xsh-lib/core 的 bash 库的一部分,语法为 xsh /util/getopts/extra

    【讨论】: