bash - 如何创建一个可以通过位置参数和命名参数接受信息的通用 Bash 函数

标签 bash command-line-arguments getopt getopts

我正在编写大量 Bash 函数,这些函数能够从使用位置参数或命名参数(由 getopts 提供)传递的命令行获取不同的信息。这个想法是,位置参数主要用于快速性和直接的人类控制,而命名参数主要用于清晰性和其他函数的控制。为了说明我的想法,请考虑一个可以从一种事物转换为另一种事物的函数。一般来说,该功能可以在快速模式或高级模式下使用。在快速模式下,指定的参数很少,通常是位置参数,而在高级模式下,可以指定很多参数,通常是命名参数。例如...

快速模式

可以通过以下方式使用此模式:

function fileName1 fileName2

它使用内部假设和自主测量将一个文件转换为另一个文件。

高级模式

可以通过以下方式使用此模式:

function -i fileName1 -o fileName2 -m -r 100 -v

该模式还可以通过以下方式使用:

function -m -v fileName1 fileName2 -r 100

请注意-v不接受任何争论。它只是一个选项(指定诸如详细程度之类的内容)。


因此,这种情况下的逻辑是,第一个位置参数被假定为 fileName1第二个位置参数假设为 fileName2 除非使用-i指定这些文件名中的任何一个或-o选项,在这种情况下使用它们是因为它们被赋予了更高的优先级(并且第一个和第二个位置参数被忽略)。

我请求以尽可能通用的方式实现这些类型的需求的建议和指导,因为这种方法将应用于包含 150 多个函数的库。

最佳答案

请注意,如果您使用 getoptsall positional arguments must come after any options 。第二个警告是,如果您使用 getopts 解析函数的参数,则在解析任何选项后,您必须将全局 OPTIND 变量重置为 1 。否则我认为解决方案很简单:

argparse.sh

#!/usr/bin/env bash

func() {
    local args=$*
    local input output verbose
    local r="unset" m=0 verbose=0

    while getopts i:o:mr:v opt; do
        case "$opt" in
            i) input="$OPTARG" ;;
            o) output="$OPTARG" ;;
            r) r="$OPTARG" ;;
            m) m=1 ;;
            v) verbose=1 ;;
        esac
    done
    shift $((OPTIND-1))
    OPTIND=1    # reset global variable

    [[ $input ]]  || input=$1
    [[ $output ]] || output=$2

    echo "=== func $args ==="
    echo "input: $input"
    echo "output: $output"
    echo "verbose: $verbose"
    echo "r: $r"
    echo "m: $m"
    echo
}

func fileName1 fileName2
func -i fileName1 -o fileName2 -m -r 100 -v
func -m -v -r 100 fileName1 fileName2

输出

=== func fileName1 fileName2 ===
input: fileName1
output: fileName2
verbose: 0
r: unset
m: 0

=== func -i fileName1 -o fileName2 -m -r 100 -v ===
input: fileName1
output: fileName2
verbose: 1
r: 100
m: 1

=== func -m -v -r 100 fileName1 fileName2 ===
input: fileName1
output: fileName2
verbose: 1
r: 100
m: 1

关于bash - 如何创建一个可以通过位置参数和命名参数接受信息的通用 Bash 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20764845/

相关文章:

php - 如何从 bash 和 php 脚本更新 Bugzilla 错误?

bash - 将 bash for 循环与 bash 脚本的嵌入式 applescript 结合使用

command-line - 可以用作参数的文本长度是否有限制?如果是的话限制是多少?

list - 在 Scala 中从命令行参数创建列表

c - 如何从 optarg 获取值

C - 如何允许 Argp 或 Getopt 中无法识别的选项?

linux - Spark-submit 在错误的目录中查找

windows - 如何配置 Windows 终端以启动 Cygwin (mintty) bash?

mysql - 如何从命令行设置 MySQL session wait_timeout?

c - 我对 getopt() 的理解正确吗?