我想创建一个bash脚本,可以按如下方式执行:
bash myscript.sh -n n -k k -p1 p1 -p2 p2
其中n,k,p1,p2
是一些参数,-n, -k, -p1, -p2
表示指定了哪些参数。我希望能够解析它们。显而易见的解决方案是使用getopt
,因为有多个选项的名称由多个字符组成,所以它不起作用。像这样迭代$@
变量:
for op in $@ ...
也不好,因为我无法访问邻居。有没有办法迭代列表'通常',这样的事情?
for i in {1..$@}; do
case ${$i} in
-n) # do something, accessing ${i+1}
...
esac
done
答案 0 :(得分:3)
您可以在处理完选项后使用shift
删除选项。
while (($# > 0)); do
case $1 in
-n) use $2; shift 2;;
-k) use $2; shift 2;;
-p1) use $2; shift 2;;
-p2) use $2; shift 2;;
*) echo "Unrecognized option $1" >&2; exit 1;;
esac
done
答案 1 :(得分:2)
John Kugelman's helpful answer是要走的路,只是为了展示如何通过基于数组索引的$@
访问来完成,(伪)输入参数数组,涉及shell算法:
for (( i = 1; i <= $#; i+=2 )); do
this=${!i} # get argument with (1-based) index i; same as: ${@:i:1}
next=${@:i+1:1} # get argument i + 1
case $this in
-n) echo "$this value: [$next]";;
-k) echo "$this value: [$next]";;
-p1) echo "$this value: [$next]";;
-p2) echo "$this value: [$next]";;
*) echo "Unrecognized option: $this" >&2; exit 1;;
esac
done
请注意,此代码段会做出以下假设,这使得它不适合大多数实际用途:
至于您尝试过的内容:
按{1..$@}
,您可能需要{1..$#}
来枚举所有索引($#
是输入参数的 count ),但是,这不是&# 39; t工作要么,因为brace expansion仅适用于文字值,不幸的是。 有解决方法,但they're not pretty。
请注意,从Bash数组获取索引列表的常用方法是不使用伪数组$@
:
${!@}
产生空字符串
将$@
复制到真正的数组 工作:args=( "$@" ); echo "${!args[@]}"
在这种情况下,最好的解决方案是使用上面演示的C风格的for
循环。
${$i}
试图访问i
- 参数在Bash中语法无效;然而, 的工作原理是使用variable indirection:谢谢,rici
如果$i
等于2
,则${!i}
等同于$2
。
但是,此语法不适用于计算的索引(除非您不方便地定义其他变量,例如iPlus1=$(( i + 1 ))
,然后使用${!iPlus1}
)。
幸运的是,当涉及基于索引的元素访问时,$@
的行为类似于常规的Bash数组(除了第一个元素具有索引1
, 0
):
因此,${!i}
相当于${@:i:1}
,它会返回索引为1
的($i
)元素 - 请注意我是如何使用<在索引规范中引用$
时,em> no $i
前缀,因为它在arithmetic context中进行评估,其中$
- 前缀变量引用是可以执行可选的简单整数计算。
这样可以根据计算索引启用元素访问:可以使用$i + 1
访问索引为${@:i+1:1}
的元素。