使用 getopts (bash) 的多个选项参数

Posted

技术标签:

【中文标题】使用 getopts (bash) 的多个选项参数【英文标题】:Multiple option arguments using 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

【问题讨论】:

这可能会有所帮助:***.com/a/7530327/1983854 需要更多细节。当给定getoptz.sh -s a -b c 时,你想要什么行为? -b-s 的参数,还是 - 表示新选项? 与Calling different programs with different options and different arguments for each option 相关但绝不重复。一般最好使用标准的命令界面指南POSIX Utility Conventions 【参考方案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

【讨论】:

以上是关于使用 getopts (bash) 的多个选项参数的主要内容,如果未能解决你的问题,请参考以下文章

具有多个强制性选项的 bash getopts

Bash getopts,参数没有被传递给选项

使用多个参数解析命令行选项 [getopt?]

Bash getopts:识别否定选项(-x- 或 +x)?

使用 getopt 处理命令行长参数

如何在 Bash 中使用 getopt 和长选项?