我正在编写大量 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 多个函数的库。
最佳答案
请注意,如果您使用 getopts
,all 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/