迭代bash脚本参数

时间:2016-06-04 16:07:44

标签: bash shell

我想创建一个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

2 个答案:

答案 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

请注意,此代码段会做出以下假设,这使得它不适合大多数实际用途:

  • 您的脚本仅支持选项,而不支持操作数(非选项参数)。
  • 所有选项都需要一个option-argument,并且必须通过空格与选项分开。

至于您尝试过的内容:

{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数组(除了第一个元素具有索引10):

  • 因此,${!i}相当于${@:i:1},它会返回索引为1的($i)元素 - 请注意我是如何使用<在索引规范中引用$时,em> no $i前缀,因为它在arithmetic context中进行评估,其中$ - 前缀变量引用是可以执行可选的简单整数计算。

  • 这样可以根据计算索引启用元素访问:可以使用$i + 1访问索引为${@:i+1:1}的元素。