在Bash函数中使用getopts

Mag*_*nus 43 bash function getopts

我想getopts在我的.bash_profile中定义的函数内部使用.我的想法是,我想将一些标志传递给此函数以改变其行为.

这是代码:

function t() {
    echo $*
    getopts "a:" OPTION
    echo $OPTION
    echo $OPTARG
}
Run Code Online (Sandbox Code Playgroud)

当我这样调用它时:

t -a bc
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

-a bc
?
 
Run Code Online (Sandbox Code Playgroud)

怎么了?我想在bc没有手动移位和解析的情况下获得该值.如何getopts在函数内正确使用?

编辑:纠正我的代码片段尝试$ OPTARG,无济于事

编辑#2:好的事实证明代码没问题,我的shell被搞砸了.打开一个新窗口解决了它.arg值确实在$ OPTARG中.

Adr*_*rth 91

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

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
Run Code Online (Sandbox Code Playgroud)

示例运行:

$ ./t.sh
a: [], non-option arguments:
a: [bc], non-option arguments: bar quux
foo: [-a <arg>]
Run Code Online (Sandbox Code Playgroud)

如果你注释掉# local OPTIND,这就是你得到的:

$ ./t.sh
a: [], non-option arguments:
a: [bc], non-option arguments: bar quux
a: [bc], non-option arguments:
Run Code Online (Sandbox Code Playgroud)

除此之外,它的用法与在函数外使用时的用法相同.

  • @ceving 1)这是编码风格的问题,但是,不,根据语言定义,这不是必需的。2)同意,这些应该是本地的。3)如您所说,在我的示例中,出口*将*退出脚本。当然,“退出”不会退出子外壳,但这不是该问题的特定问题。您不必使用`set -e`,只需要确保捕获错误和`MSG = $(foo ...)||就可以了。die`也一样。set -e是解决该问题的一种方法[但是它不是傻瓜式的](http://mywiki.wooledge.org/BashFAQ/105),我和许多其他人一样,不建议使用它。 (2认同)

ken*_*orb 11

这是getoptsshell函数中使用的简单示例:

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

输出:

$ ./test.sh -a bc
Input: -a bc, OPTION: a, OPTARG: bc
Input: -a foo, OPTION: a, OPTARG: foo
Run Code Online (Sandbox Code Playgroud)

正如@Adrian指出的那样,local OPTIND(或OPTIND=1)需要设置为shell OPTIND多次调用getopts(man bash)之间不会自动重置.

基本语法getopts是:

getopts OPTSTRING VARNAME [ARGS...]
Run Code Online (Sandbox Code Playgroud)

默认情况下,不指定参数等效于使用"$ @"显式调用它,即:getopts "a:" opts "$@".

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

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

更多信息,请参阅:The Bash Hackers Wiki上的小傀儡教程


Ans*_*ers 5

参数存储在varable中$OPTARG.

function t() {
  echo $*
  getopts "a:" OPTION
  echo $OPTION
  echo $OPTARG
}
Run Code Online (Sandbox Code Playgroud)

输出:

$ t -a bc
-a bc
a
bc
Run Code Online (Sandbox Code Playgroud)