使Groovy成为有吸引力的脚本语言的众多功能之一是通过CliBuilder内置的命令行参数支持。 之前,我在自定义Groovy的CliBuilder使用声明以及使用Groovy CliBuilder显式指定'args'属性的文章中写过有关CliBuilder的文章。 在本文中,我研究了Groovy的CliBuilder对通过单个命令行标志传递的多个参数的支持 。
Groovy API文档包括有关CliBuilder的这句话:
nbsp;
请注意使用一些特殊的符号。 通过将“ s”添加到可能多次出现并具有参数的选项上,或者在这种情况下使用valueSeparator分隔多个参数值会导致返回相关参数值的列表。
如本文档所述,Groovy的内置CliBuilder
支持允许将已解析的命令行标志视为具有多个值,并且引用此参数的约定是在命令行选项的“短”名称后添加“ s” 。 这样做使与单个标志关联的多个值可以作为String的集合使用,可以很容易地对其进行迭代以访问多个值。
在定制Groovy的CliBuilder使用声明一文中 ,我简要地介绍了该功能支持通过单个命令行参数传递给脚本的多个值。 我在这篇文章中描述了该功能,如下所示:
对单个参数使用多个值也可能非常有用。 直接使用Apache Commons CLI的Option类(特别是其UNLIMITED_VALUES常量字段)使开发人员可以与CliBuilder交流,此选项需要解析可变数量的值。 分隔这些多个值的字符(在此示例中为常见字符)也必须通过“ valueSeparator”指定字符来指定。
可以通过修改脚本来查找包含在JAR文件中的类文件的脚本来证明这种由Apache CLI驱动的 Groovy功能的有用性,这在我用Groovy搜索JAR文件一文中已经谈到。 该文章中的脚本递归地在一个目录中搜索了一个指定的String,该字符串包含在搜索到的JAR中。 对该脚本进行一些小的调整即可更改它,以便它可以支持多个指定目录以递归搜索多个表达式。
修改后的脚本如下所示。
#!/usr/bin/env groovy
/**
* findClassesInJars.groovy
*
* findClassesInJars.groovy -d <<root_directories>> -s <<strings_to_search_for>>
*
* Script that looks for provided String in JAR files (assumed to have .jar
* extensions) in the provided directory and all of its subdirectories.
*/
def cli = new CliBuilder(
usage: 'findClassesInJars.groovy -d <root_directories> -s <strings_to_search_for>',
header: '\nAvailable options (use -h for help):\n',
footer: '\nInformation provided via above options is used to generate printed string.\n')
import org.apache.commons.cli.Option
cli.with
{
h(longOpt: 'help', 'Help', args: 0, required: false)
d(longOpt: 'directories', 'Two arguments, separated by a comma', args: Option.UNLIMITED_VALUES, valueSeparator: ',', required: true)
s(longOpt: 'strings', 'Strings (class names) to search for in JARs', args: Option.UNLIMITED_VALUES, valueSeparator: ',', required: true)
}
def opt = cli.parse(args)
if (!opt) return
if (opt.h) cli.usage()
def directories = opt.ds
def stringsToSearchFor = opt.ss
import java.util.zip.ZipFile
import java.util.zip.ZipException
def matches = new TreeMap<String, Set<String>>()
directories.each
{ directory ->
def dir = new File(directory)
stringsToSearchFor.each
{ stringToFind ->
dir.eachFileRecurse
{ file->
if (file.isFile() && file.name.endsWith('jar'))
{
try
{
zip = new ZipFile(file)
entries = zip.entries()
entries.each
{ entry->
if (entry.name.contains(stringToFind))
{
def pathPlusMatch = '${file.canonicalPath} [${entry.name}]'
if (matches.get(stringToFind))
{
matches.get(stringToFind).add(pathPlusMatch)
}
else
{
def containingJars = new TreeSet<String>()
containingJars.add(pathPlusMatch)
matches.put(stringToFind, containingJars)
}
}
}
}
catch (ZipException zipEx)
{
println 'Unable to open file ${file.name}'
}
}
}
}
}
matches.each
{ searchString, containingJarNames ->
println 'String '${searchString}' Found:'
containingJarNames.each
{ containingJarName ->
println '\t${containingJarName}'
}
}
第11至28行是应用Groovy内部CliBuilder
位置。 在第20和21行中设置了“目录”(“ d”的短名称)和“字符串”(“ s”的短名称)命令行标志。这些行使用Option.UNLIMITED_VALUES
指定多个适用于每个参数,它们还使用valueSeparator
指定用于分隔每个标志的多个值的标记(在这种情况下为逗号)。
第27-28行获取每个参数的多个值。 尽管这些选项的简称为“ d”和“ s”,但在每个选项(现在为“ ds”和“ ss”)后附加“ s”可以访问它们的多个值。 脚本的其余部分利用了这些优势,并遍历了与每个标志关联的多个字符串。
下一个屏幕快照演示了上面的脚本正在执行。
上面的屏幕快照演示了能够为单个命令行标志提供多个值的实用程序。 Groovy对Apache CLI的内置支持使使用可自定义的命令行解析变得容易。
参考: Groovy: JCG合作伙伴 Dustin Marx在Inspired by Actual Events博客上为单个命令行选项提供了多个值 。
翻译自: https://www.javacodegeeks.com/2012/12/groovy-multiple-values-for-a-single-command-line-option.html