如何包装另一个仍然按原样传递$ OPTIND的shell?

时间:2011-04-29 15:59:56

标签: bash scripting code-reuse getopts

我正在尝试使用脚本a包装bash脚本b。 但是我想将传递给a的选项传递给b。

#!/bin/bash

# script a
./b ${@:$OPTIND}

这也将打印1美元(如果有的话)。什么是最简单的方法?

所以打电话:

./a -c -d 5 first-arg

我希望b执行: ./b -c -d 5#WITHOUT first-arg

3 个答案:

答案 0 :(得分:1)

在bash中,您可以构建一个包含选项的数组,并使用该数组来调用辅助程序。

call_b () {
  typeset -i i=0
  typeset -a a; a=()
  while ((++i <= OPTIND)); do   # for i=1..$OPTIND
    a+=("${!i}")                # append parameter $i to $a
  done
  ./b "${a[@]}"
}
call_b "$@"

在任何POSIX shell(ash,bash,ksh,shsh或ksh仿真中的zsh,......)中,您可以使用"$1" "$2" …构建一个列表并使用eval来设置不同的位置参数。

call_b () {
  i=1
  while [ $i -le $OPTIND ]; do
    a="$a \"\$$i\""
    i=$(($i+1))
  done
  eval set -- $a
  ./b "$@"
}
call_b "$@"

通常,这在zsh中相当容易。

./b "${(@)@[1,$OPTIND]}"

答案 1 :(得分:0)

您为什么使用${@:$OPTIND}而不只是$@$*

${parameter:index}语法表示使用index来解析$parameter。如果您使用的是$@,则会使用index作为参数的索引。

$ set one two three four #Sets "$@"
$ echo $@
one two three four
$ echo ${@:0}
one two three four
$ echo ${@:1}
one two three four
$ echo ${@:2}
two three four

$OPTIND实际上仅在您使用getopts时使用。这会计算getopts处理$@中参数的次数。根据{{​​3}}:

  

每次调用shell或shell脚本时,OPTIND都会初始化为1。

这可以解释为什么你不断获得1的价值。


编辑回应编辑问题

  

@David - “./ b $ @”仍打印传递给a的参数(参见Q编辑)。我想只传递a而不是args的选项

所以,如果我执行:

$ a -a foo -b bar -c fubar barfu barbar

你想传递给b:

$ b -a foo -b bar -c fubar

但不是

$ b -arg1 foo -arg2 bar -arg3 fubar barfu barbar

那会很棘手......

是否有理由不能将整行传递给b并忽略它?

我相信可以使用正则表达式:

$ echo "-a bar -b foo -c barfoo foobar" | sed 's/\(-[a-z] [^- ][^- ]*\)  *\([^-][^-]*\)$/\1/'
-a bar -b foo -c barfoo

我不能保证这个正则表达式适用于所有情况(即如果没有参数会怎样?)。基本上,我将它锚定到行的末尾,然后匹配最后一个参数和参数以及行的其余部分。我只使用最后一个参数和参数进行替换。

我已经在几种情况下对其进行了测试,但您最好使用getopts来捕获参数,然后将这些参数传递给b,或者只是b如果可能的话,忽略那些额外的论点。

答案 2 :(得分:0)

为了将命令选项与常规参数分开,您需要知道哪些选项采用参数,哪些选项独立。
在示例命令中:

./a -c -d 5 first-arg
  • -c-d可能是独立选项,5 first-arg是常规参数
  • 5可能是-d选项的参数(这似乎就是你的意思)
  • -d可能是-c选项的参数,并且(如第一种情况)5 first-arg常规参数。

以下是我处理它的方式,假设-a-b-c-d是唯一选项,-b和{{ 1}}是唯一采用选项参数的人。请注意,有必要解析所有选项,以确定它们的结束位置。

-d

整个#!/bin/bash while getopts ab:cd: OPT; do case "$OPT" in a|b|c|d) : ;; # Don't do anything, we're just here for the parsing ?) echo "Usage: $0 [-ac] [-b something] [-d something] [args...]" >&2 exit 1 ;; esac done ./b "${@:1:$((OPTIND-1))}" 循环只是为了计算OPTIND。 while命令中的ab:cd:定义允许哪些选项以及哪些选项采用参数(以冒号表示)。神秘的最终表达意味着“参数数组的元素1到OPTIND-1,作为单独的单词传递”。