在Bash函数中使用getopts

在Bash函数中使用getopts,bash,function,getopts,Bash,Function,Getopts,我想在我在.bash_配置文件中定义的函数中使用getopts。 我想把一些标志传递给这个函数来改变它的行为 代码如下: function t() { echo $* getopts "a:" OPTION echo $OPTION echo $OPTARG } 当我这样调用它时: t -a bc 我得到这个输出: -a bc ?   怎么了?我希望在不手动移位和解析的情况下获取值bc。如何在函数中正确使用getopts 编辑:更正了我的代码片段以尝试$OP

我想在我在.bash_配置文件中定义的函数中使用
getopts
。 我想把一些标志传递给这个函数来改变它的行为

代码如下:

function t() {
    echo $*
    getopts "a:" OPTION
    echo $OPTION
    echo $OPTARG
}
当我这样调用它时:

t -a bc
我得到这个输出:

-a bc
?
 
怎么了?我希望在不手动移位和解析的情况下获取值
bc
。如何在函数中正确使用
getopts

编辑:更正了我的代码片段以尝试$OPTARG,但无效


编辑#2:好的,代码很好,我的shell不知怎么搞砸了。打开一个新窗口解决了这个问题。arg值实际上是以$OPTARG为单位的

参数存储在变量
$OPTARG

function t() {
  echo $*
  getopts "a:" OPTION
  echo $OPTION
  echo $OPTARG
}
输出:

$ t -a bc
-a bc
a
bc
$ ./test.sh -a bc
Input: -a bc, OPTION: a, OPTARG: bc
Input: -a foo, OPTION: a, OPTARG: foo
$t-a bc
-公元前
A.

bc
正如@Ansgar所指出的,选项的参数存储在
${OPTARG}
中,但在函数内部使用
getopts
时,这并不是唯一需要注意的事情。您还需要通过取消设置函数或将其声明为
local
,确保函数的
${OPTIND}
是本地的,否则在多次调用函数时会遇到意外行为

t.sh

#!/bin/bash

foo()
{
    foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; }

    local OPTIND o a
    while getopts ":a:" o; do
        case "${o}" in
            a)
                a="${OPTARG}"
                ;;
            *)
                foo_usage
                ;;
        esac
    done
    shift $((OPTIND-1))

    echo "a: [${a}], non-option arguments: $*"
}

foo
foo -a bc bar quux
foo -x
除此之外,它的用法与在函数外部使用时相同。

以下是在shell函数中使用的简单示例:

#!/usr/bin/env bash
t() {
  local OPTIND
  getopts "a:" OPTION
  echo Input: $*, OPTION: $OPTION, OPTARG: $OPTARG
}
t "$@"
t -a foo
输出:

$ t -a bc
-a bc
a
bc
$ ./test.sh -a bc
Input: -a bc, OPTION: a, OPTARG: bc
Input: -a foo, OPTION: a, OPTARG: foo
正如,
localoptind
(或
OPTIND=1
)需要设置,因为shell不会在(
manbash
)之间自动重置
OPTIND

getopts
的基本语法是:

getopts OPTSTRING VARNAME [ARGS...]
默认情况下,不指定参数相当于使用“$@”显式调用它,即:
getopts“a:“opts”$@

如果出现问题,这些是
getopts
用来检查的变量:

  • OPTIND
    -要处理的下一个参数的索引
  • OPTARG
    -变量设置为由
    getopts
    找到的选项的任何参数
  • OPTERR
    (非POSIX)-设置为0或1以指示Bash是否应显示由
    getopts
    生成的错误消息

更多信息,请参阅:在Bash黑客维基

抱歉,我错误地粘贴了我的代码片段。。。我还回显$OPTARG,这是第三行,空白。还有其他想法吗?@Magnus可能是因为您多次调用该函数,
$OPTIND
没有在本地定义(请参见Adrian的答案)。虽然我很感激您接受了我的答案,但您可能更愿意接受他的答案。代码仅在粘贴到shell中时有效,而在脚本中无效。@kenorb它在脚本中工作得很好。我不是编造出来的。好吧,我不确定如何调用
t
,我必须在脚本中调用
t-abc
,或者添加
t“$@”
,最初我认为它不需要。1.
1>&2
中的
1
。2.)您没有将
a
o
OPTARG
定义为本地。3.
exit
将不会退出脚本,而只是一个子shell。要退出脚本,必须在外壳中设置-e,并在子外壳中设置退出1。该示例不会引发问题,但一个
MSG=$(foo…
会解决问题。@ceving 1)这是一个编码风格的问题,但根据语言定义,这不是必需的。2) 同意,这些应该是本地的。3) 正如您所说,在我的示例中,退出将退出脚本。当然,
exit
不会退出子shell,但这不是此问题的具体问题。您不必使用
set-e
,只需确保捕捉到错误,
MSG=$(foo…)| die
也能正常工作
set-e
是解决此问题的一种方法,我和其他许多人一样,不建议使用它。只需指出,即使您在函数中没有使用OPTIND(例如,使用
shift;
),它仍然需要本地化,以便具有可预测的行为。@ceving,您可以查看这里,-我添加了
local
,但没有很好地给出答案。我不知道它是否有效,但做得很好。@kenorb,你可以在这里查看->,添加了
local
,但没有帮助