遍历 bash 脚本参数



我想创建一个可以按如下方式执行的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

您可以在处理选项后使用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

John Kugelman 的有用答案是要走的路,但只是为了展示如何通过基于数组索引的访问来完成它$@,输入参数的(伪)数组,涉及 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..$#}为了枚举所有索引($#是输入参数的计数),但是,这也不起作用,因为不幸的是,大括号扩展仅适用于文字值。有解决方法,但它们并不漂亮。

请注意,从 Bash 数组获取索引列表的常用方法不适用于伪数组$@

  • ${!@}生成空字符串

  • 而首先将$@复制到真正的数组确实有效args=( "$@" ); echo "${!args[@]}"

在这种情况下,最好的解决方案是使用上面演示的 C 样式for循环。

${$i}尝试访问i-th 参数在 Bash 中语法无效;然而,起作用的是使用变量间接:谢谢,rici
例如,$i等于2时,${!i}等价于$2

但是,此语法不适用于计算索引(除非您笨拙地定义其他变量,例如iPlus1=$(( i + 1 ))然后使用${!iPlus1})。

然而,幸运的是,当涉及到基于索引的元素访问时,$@的行为确实像常规的 Bash 数组(除了第一个元素有索引1,而不是0):

  • 因此,${!i}等价于${@:i:1},它返回索引$i的 (1) 元素 - 请注意,在索引规范中引用$i时,我没有使用$前缀前缀,因为它是在算术上下文中计算的,其中$前缀变量引用是可选的,并且可以执行简单的整数计算。

  • 这允许基于计算索引的元素访问:具有索引$i + 1的元素可以使用${@:i+1:1}访问。

相关内容

  • 没有找到相关文章

最新更新