Одной из многих функций, которые делают Groovy привлекательным языком сценариев, является встроенная поддержка аргументов командной строки через CliBuilder . Ранее я писал о CliBuilder в статьях « Настройка операторов Groovy для использования CliBuilder и явное указание свойства « args »с помощью Groovy CliBuilder» . В этой статье я расскажу о поддержке Cliovuilder в Groovy нескольких аргументов, передаваемых через один флаг командной строки.
Документация Groovy API включает в себя следующее предложение о CliBuilder :
NBSP;
Обратите внимание на использование некоторых специальных обозначений. Добавление ‘s’ к опции, которая может появляться несколько раз и имеет аргумент, или, как в этом случае, использование valueSeparator для разделения нескольких значений аргумента, приводит к возврату списка связанных значений аргумента.
Как указано в этой документации, встроенная в CliBuilder
поддержка CliBuilder
позволяет обрабатывать флаг анализируемой командной строки как имеющий несколько значений, и CliBuilder
для ссылки на этот аргумент является добавление «s» после «короткого» имени параметра командной строки , Это делает несколько значений, связанных с одним флагом, доступными в виде набора строк, которые можно легко перебрать для доступа к нескольким значениям.
В посте « Настройка операторов Groovy для использования CliBuilder» я кратко рассмотрел функцию, поддерживающую несколько значений, передаваемых в сценарий через один аргумент командной строки. Я описал функцию в этом посте следующим образом:
Использование нескольких значений для одного аргумента также может быть очень полезным. Непосредственное использование класса Option класса CLI Apache Commons (и в частности его константного поля UNLIMITED_VALUES ) позволяет разработчику сообщить CliBuilder, что для этой опции необходимо проанализировать переменное число значений. Символ, который разделяет эти множественные значения (в этом примере — обычное), также должен быть указан путем указания символа через ‘valueSeparator.’
Полезность этой функции Groovy с Apache CLI- питанием можно продемонстрировать, адаптировав скрипт для поиска файлов классов, содержащихся в файлах JAR, о которых я говорил в статье Поиск файлов JAR с помощью Groovy . Сценарий в этом посте рекурсивно искал в одном каталоге одну указанную строку, содержащуюся как запись в найденных файлах JAR. Несколько незначительных изменений в этом скрипте изменяет его так, что он может поддерживать несколько указанных каталогов для рекурсивного поиска нескольких выражений.
Пересмотренный сценарий показан далее.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
#!/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 применяется внутренний CliBuilder
Groovy. Флаги командной строки ‘directoryies’ (короткое имя ‘d’) и ‘strings’ (короткое имя ‘s’) устанавливаются в строках 20 и 21. Эти строки используют Option.UNLIMITED_VALUES
для указания нескольких значений, применимых для каждый аргумент, и они также используют valueSeparator
для указания токена, разделяющего несколько значений для каждого флага (запятая в этих случаях).
Строки 27-28 получают несколько значений для каждого аргумента. Хотя параметры имели короткие имена «d» и «s», добавление «s» к каждому из них (теперь «ds» и «ss») позволяет получить доступ к их множественным значениям. Остальная часть сценария использует их и выполняет итерацию по нескольким строкам, связанным с каждым флагом.
Следующий снимок экрана демонстрирует выполнение вышеуказанного сценария.
Приведенный выше снимок экрана демонстрирует полезность предоставления нескольких значений для одного флага командной строки. Встроенная в Groovy поддержка Apache CLI упрощает использование настраиваемого анализа командной строки.
Ссылка: Groovy: несколько значений для одного параметра командной строки от нашего партнера по JCG Дастина Маркса в блоге Inspired by Actual Events .