最近一篇文章 介绍了在 Java 中解析命令行选项。因为我非常喜欢 Groovy,并且 Groovy 非常适合编写脚本,而且比较 Java 和 Groovy 解决方案也很有趣,所以我决定改写 Seth 的文章,但使用 Groovy。
安装 Groovy
Groovy 基于 Java,因此需要安装 Java。您的 Linux 发行版的存储库中可能包含最新且不错的 Java 和 Groovy 版本。或者,您可以按照 groovy-lang.org 上的说明安装 Groovy。
对于 Linux 用户来说,一个不错的替代方案是 SDKMan,它可以用来获取多个版本的 Java、Groovy 和许多其他相关工具。在本文中,我使用的是我的发行版的 OpenJDK11 版本和 SDKMan 的最新 Groovy 版本。
在 Groovy 中解析命令行选项
当我们创建一个脚本——一种简短的、通常是非正式的程序——从命令行运行时,我们通常遵循在命令行上传递参数的实践。一个很好的例子是 ls
命令,它用于列出给定文件夹中的所有文件和子文件夹,可能显示属性并按上次修改日期的倒序排序,如下所示
$ ls -lt /home/me
像这样显示我的主文件夹的内容
total 252
drwxr-xr-x 5 me me 4096 Aug 10 12:23 Downloads
drwx------ 11 me me 4096 Aug 10 08:59 Dropbox
drwxr-xr-x 27 me me 12288 Aug 9 11:58 Pictures
-rw-rw-r-- 1 me me 235 Jul 28 16:22 wb.groovy
drwxr-xr-x 2 me me 4096 Jul 20 22:04 Desktop
drwxrwxr-x 2 me me 4096 Jul 20 15:16 Fixed
drwxr-xr-x 2 me me 16384 Jul 19 08:49 Music
-rw-rw-r-- 1 me me 433 Jul 7 13:24 foo
drwxr-xr-x 6 me me 4096 Jun 29 10:25 Documents
drwxr-xr-x 2 me me 4096 Jun 14 22:15 Templates
-rw-rw-r-- 1 me me 803 Jun 14 11:33 bar
当然,可以通过检查命令的参数并决定在每种情况下做什么来处理参数;但这最终会造成重复劳动,可以通过使用为此目的设计的库来避免。
Seth 的 Java 文章介绍了 Apache Commons CLI 库,这是一个用于处理命令行选项的出色 API。事实上,这个库非常出色,以至于开发 Groovy 的优秀人员默认在 Groovy 安装中提供了它。因此,一旦您安装了 Groovy,您就可以通过 groovy.cli.picocli.CliBuilder 访问此库,默认情况下已为您导入该库。
这是一个 Groovy 脚本,它使用这个 CLI 构建器来实现与 Seth 的 Java 程序相同的结果
1 def cli = new CliBuilder(usage: 'ho.groovy [-a] -c')
2 cli.with {
3 a longOpt: 'alpha', 'Activate feature alpha'
4 c longOpt: 'config', args:1, argName: 'config', required: true, 'Set config file'
5 }
6 def options = cli.parse(args)
7 if (!options) {
8 return
9 }
10 if (options.a) {
11 println' Alpha activated'
12 }
13 if (options.c) {
14 println "Config set to ${options.c}"
15 }
我在这里包含了行号,以便于讨论。将此脚本保存在名为 ho.groovy 的文件中,不包含行号。
在第 1 行,我们定义了变量 cli 并将其设置为 CliBuilder 的新实例,并定义了 usage 属性。这是一个字符串,如果调用 usage() 方法,它将被打印出来。
在第 2-5 行,我们使用 Groovy 添加到对象的 with() 方法,以及 CliBuilder 定义的 DSL,来设置选项定义。
在第 3 行,我们定义了选项 'a',将其 longOpt 字段设置为 'alpha',并将其描述设置为 '激活 alpha 功能'。
类似地,在第 4 行,我们定义了选项 'c',将其 longOpt 字段设置为 'config',并指定此选项接受一个名为 'config' 的参数。此外,这是一个 required 选项(听起来很有趣,我知道),其描述是 '设置配置文件'。
在这里稍微停顿一下,介绍一些背景知识,您可以在上面的 CliBuilder 链接中阅读所有关于这些各种选项的信息。更一般地说,以 longOpt: 'alpha' 形式编写的内容是 Groovy 表示法,用于将键值对条目放入 Map 实例中,您可以在 此处 阅读相关内容。在这种情况下,每个键都对应于 CliBuilder 提供的同名方法。如果您想知道像下面这样的行发生了什么
a longOpt: 'alpha', 'Activate feature alpha'
那么,值得一提的是,Groovy 允许我们在某些情况下省略括号;所以上面等同于
a(longOpt: 'alpha', 'Activate feature alpha')
即,这是一个方法调用。此外,Groovy 允许位置参数和命名参数,后者使用键:值语法。
继续!在第 6-9 行,我们调用 CliBuilder 实例 cli 的 parse() 方法,传递 args——一个由 Groovy 运行时创建的 String 值数组,其中包含来自命令行的参数。此方法返回一个选项 Map,其中键是预定义选项的短格式——在本例中为 'a' 和 'c'。如果解析失败,则 parse() 发出 usage 消息,一个合理的错误消息,并返回一个 null 值,因此我们不必使用 try-catch 块(在 Groovy 中不常看到)。所以这里——第 8 行——我们只是返回,因为我们所有的工作都为我们完成了。
在第 10-12 行,我们检查命令行中是否包含选项 'a',如果包含,则打印一条消息说明。
类似地,在第 13-15 行,我们检查命令行中是否包含选项 'c',如果包含,则打印一条消息显示为其提供的参数。
运行命令
让我们运行脚本几次;首先不带任何参数
$ groovy ho.groovy
error: Missing required option: c
usage: ho.groovy [-a] -c
-a,--alpha Activate feature alpha
-c,--config <config> Set config file
$
请注意关于缺少必需选项 'c' 的抱怨。
然后使用 'c' 选项但不带参数
$ groovy ho.groovy -c
error: Missing argument for option: c
usage: ho.groovy [-a] -c
-a,--alpha
Activate feature alpha
-c,--config <config> Set config file
$
太棒了,CliBuilder 实例方法 parse() 注意到没有为 'c' 提供参数。
最后,让我们尝试同时使用这两个选项,并为 'c' 提供一个参数,以长格式
$ groovy ho.groovy --alpha --config bar
Alpha activated
Config set to bar
$
看起来不错!
由于 'c' 选项的想法是提供一个配置文件,我们也可以告诉 CliBuilder 实例此参数的类型是 File,它将返回 File 而不是 String。但我们将其留到以后再说。
所以,这就是在 Groovy 中解析命令行选项的方法。
Groovy 资源
Groovy 网站有很多很棒的文档。另一个很棒的 Groovy 资源是 Mr. Haki,特别是 这篇关于 CliBuilder 的精彩文章。
学习 Groovy 的另一个重要原因是 Grails,这是一个非常高效的全栈 Web 框架,构建在 Hibernate、Spring Boot 和 Micronaut 等优秀组件之上。
评论已关闭。