9

我正在尝试使用 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
4

3 回答 3

14

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

#!/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
于 2013-12-24T13:39:05.073 回答
4

这是我使用用户定义函数执行此操作的方法: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

于 2021-03-21T11:15:43.563 回答
3

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

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

while [[ "$*" ]]; do
    if [[ $1 = "-s" ]]; then
        # -s takes three arguments
        args="$2 $3 $4"
        echo "-s got $args"
        shift 4
    fi
done
于 2013-04-24T12:44:15.600 回答