getopts简易教程(Small getopts tutorial)译文

getopts简易教程

当你想用一种专业的方式解析命令行参数时,getopts就是要选择的工具。和它的旧版本兄弟命令getopt不一样(注意没有s!),getopts是shell内置命令。高级地方表如今html

  • 你不须要经过一个外部命令传递参数
  • getopts能够很容易的设置一些你能用于解析参数的变量(对于一个外部程序来讲这是不可能的!)
  • 你没必要再处理过去一些使用getopt时的一些bug实现(空格, …)
  • getopts已经在POSIX®定义

一些解析位置参数的其余方法(不用getopt(s))在这里介绍了: 如何处理位置参数.算法

注意getopts不能解析GNU风格的长选项(--myoption)或XF86风格的长选项(-myoption)!shell

介绍

术语

须要先了解一下咱们这里探讨的事情,因此让咱们来看一个范例… 来看一下下面这行命令:数组

mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt

全部这些都叫位置参数,可是你能够把他们分红一些逻辑组:bash

  • -x是一个选项, 一个标识, 一个开关: 一个字符, 有一个前引导短横杠(-)
  • -f也是一个选项,可是这个选项有一个附加参数(传递给-f选项的参数): /etc/mybackup.conf。这个参数一般与它的参数分开(使用一个空格或其余分隔符), 但这不是必须的, -f/etc/mybackup.conf也是合法的。
  • -r依赖于配置。在这个范例中,-r不须要参数,因此它是独立的选项,像-x
  • ./foo.txt和./bar.txt是剩余的参数,不与任何选项关联。这些一般用做聚合参数(好比你指定给cp(1)的文件名)或者不须要选项的参数,由于这是程序的预约义格式(就像你传递给文本编辑器的文件名参数,用于打开和显示文本 - 为什么还须要一个额外的开关呢?). POSIX®调用它们做为操做对象

让你体会一下为何getopts颇有用: 上面的命令能够像这样读取…编辑器

mybackup -xrf /etc/mybackup.conf ./foo.txt ./bar.txt

…使用本身的代码去解析很困难。而getopts能够认出全部常见的选项格式。函数

选项标识能够有大小写,也能够是数字。甚至是其余可识别字符,可是并不推荐这么作(可用性差并且特殊字符可能会出问题)。工具

原理

通常你须要调用getopts好几回。每次会使用"下一个"位置参数(和一个可能的附加参数),若是解析成功,会给你返回结果。getopts不会改变位置参数的设定 —— 若是你想要shift掉参数,你必须手工处理:oop

shift $((OPTIND-1))
# now do something with $@

由于getopts在没有要解析的参数剩余时会返回退出状态_FALSE_,因此能够很容易的在while循环使用:测试

while getopts ...; do
  ...
done

getopts将会解析选项和他们可能的参数。遇到第一个非选项的参数时将会中止解析(一个不以连字符(-)开头的字符串,这不是前面任何一个选项的参数)。一样也会在看到--(双连字符)时中止解析,由于这个含义是选项终止

有用的变量

变量 描述
OPTIND 保存下一个要解析的参数的指针。这就是getopts如何"记住"本身的状态和回调请求。一样能够用于在getopts处理过以后shift掉位置参数。OPTIND初始为1, 若是你想要再次使用getopts解析任何参数时须要从新设置为1
OPTARG 这个变量设置为被getopts发现的选项的参数。一样包含了未知的选项标记
OPTERR (可选值0或1)代表Bash是否应该显示getopts内置的错误信息。该值在每一个shell启动的时候会被初始化为1 - 因此若是你不想看到烦人的信息请务必设置为0!

getopts一样使用这些变量用于错误报告(they're set to value-combinations which arent possible in normal operation).#括号里面的不会翻译,预留

指明你想要作的

getopts的基本语法是:

getopts OPTSTRING VARNAME [ARGS...]

解释:

选项 说明
OPTSTRING 告诉getopts指望哪一个选项和指望的参数在哪里(参考下面的)
VARNAME 告诉getopts哪一个shell变量用于选项报告
ARG 告诉getopts将这些解析为附加单词而不是位置参数

option-string

option-string告诉getopts指望哪一个选项,而且哪一个选项必须有参数。语法很是简单 -- 每一个字母就是选项名自己,下面这个范例告诉getopts寻找-f, -A和-x:

getopts fAx VARNAME

当你想让getopts对某个选项指望一个参数时,只是在这个选项标记后面放置一个:(冒号)。若是你想让-A指望一个参数(例如变成 -A SOMETHING),只须要:

getopts fA:x VARNAME

若是option-string首个字母是:(冒号),一般是荒谬的,由于没有任何选项在它以前,这种状况下,getopts会切换到"静默错误报告"模式。在产品脚本中,这一般就是你想要的结果(自行抓取错误信息处理,不要被烦人的信息所干扰)。

自定义参数解析

getopts工具会默认解析当前shell或函数的位置参数(意味着它解析的是"$@")。

你能够给出你本身的一组参数解析。当附加参数在VARNAME参数以后给出时,getopts并不试图解析这些位置参数。

用这种方式,你能够按照你喜欢的方式解析任何选项,这里是一个数组的范例:

while getopts :f:h opt "${MY_OWN_SET[@]}"; do
  ...
done

不带这些附加参数调用getopts的方式等同于显式的使用"$@"调用:

getopts ... "$@"

错误报告

关于错误报告,getops能够在两种模式下运行:

  • 详尽模式
  • 安静模式

对于产品脚本我建议使用静默模式,由于这样看起来更专业,你不想看到更多烦人的信息。一样也更容易处理,失败的用例都以更简单的方式显示。

详尽模式

选项 说明
invalid option VARNAME is set to ? (quersion-mark) and OPTARG is unset
required argument not found VARNAME is set to ? (quersion-mark), OPTARG is unset and an error message is printed

安静模式

选项 说明
invalid option VARNAME is set to ? (question-mark) and OPTARG is set to the (invalid) option character
required argument not found VARNAME is set to : (colon) and OPTARG contains the option-character in question

开搞

第一个例子

足够说明一些问题!

让咱们先看一个很是简单的实例: 只有一个指望的选项(-a),没有任何参数。一样咱们用带:(冒号)的option string为了禁用详尽错误显示:

#!/bin/bash

while getopts ":a" opt; do
  case $opt in
    a)
      echo "-a was triggered!" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      ;;
  esac
done

我把这些内容放到一个文件go_test.sh,就是你接下来看到的范例中的名字。

来让咱们作一些测试:

不带任何参数调用

$ ./go_test.sh
$

什么都没发生?对的,getopts没看到任何合法或非法的选项(前面有短横线的字母),因此不会触发。

以非选项的参数调用

$ ./go_test.sh /etc/passwd
$

仍是 — 什么都没发生。很是相似的用例: getopts没看到任何合法或非法的选项(前面有短横线的字母),因此不会触发。

传递给你的脚本的参数固然能够用$1 - ${N}获取。

用选项参数调用

如今让咱们触发一下getopts: 提供选项。

首先,来一个非法的:

$ ./go_test.sh -b
Invalid option: -b
$

和预期的同样,getopts不容许这个选项,像上面说的同样: It placed ? into $opt and the invalid option character (b) into $OPTARG. 咱们的用例就验证了这一点。

如今,来一个合法的(-a):

$ ./go_test.sh -a
-a was triggered!
$

你看到了,这个探测结果运行的很完美。在咱们的用例a选项放在了变量$opt中。

固然在调用的时候能够组合有效和无效的选项:

$ ./go_test.sh -a -x -b -c
-a was triggered!
Invalid option: -x
Invalid option: -b
Invalid option: -c
$

最后,天然也能够屡次给出咱们的选项:

$ ./go_test.sh -a -a -a -a
-a was triggered!
-a was triggered!
-a was triggered!
-a was triggered!
$

最后一个例子让咱们须要考虑到几点:

  • 无效选项并不中止处理过程: 若是你想停掉脚本,你必须本身处理(在正确位置退出)
  • 多个相同选项是可行的: 若是你你不容许这么作,你必须本身检测(例如,设置一个变量或其余方式)

一个带参数的选项

让咱们把上面的例子扩展一下。只有一点点:

  • -a如今须要一个参数-a now takes an argument
  • 遇到错误,解析过程以exit 1退出
#!/bin/bash

while getopts ":a:" opt; do
  case $opt in
    a)
      echo "-a was triggered, Parameter: $OPTARG" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

让咱们继续作和最后一个范例一样的测试:

不用任何参数调用

$ ./go_test.sh
$

像上面同样,什么都没发生。就没触发。

以非选项的参数调用

$ ./go_test.sh /etc/passwd
$

很是相似的状况: 没有触发。

带参数选项调用

非法选项:

$ ./go_test.sh -b
Invalid option: -b
$

和指望的同样,像上面同样,getopts不容许这个选项,和程序算法吻合。

合法选项,可是不带强制要求的参数:

$ ./go_test.sh -a
Option -a requires an argument.
$

选项OK,可是丢掉了一个参数。

让咱们提供这个参数:

$ ./go_test.sh -a /etc/passwd
-a was triggered, Parameter: /etc/passwd
$

参考资料

相关文章
相关标签/搜索