#scala #parsing #arguments #command-line-interface
Вопрос:
У меня есть небольшой модуль, который требует разбора аргументов командной строки с дополнительными параметрами.
Функция должна извлечь необходимые параметры, возвращая их, а также возвращая любые дополнительные аргументы, которые не были указаны в отдельном списке.
Комментарии:
1. Я не получаю пониженных голосов. Если это вам не полезно, не обращайте на это внимания. Если логика неверна, опубликуйте лучшую версию.
Ответ №1:
Я обнаружил, что эта функция работает довольно хорошо. Также добавлены некоторые scaladoc и спецификация для документирования и тестирования
Какие-либо улучшения, чтобы сделать его более «идиоматичным»?
Модуль:
import scala.collection.mutable.ListBuffer
object Utilities {
/**
* Parses command line arguments
*
* This function parses command line arguments from `args`, as
* an `Array[String]`.
* The parameters to be extracted can be prefixed with `-` as default or
* the param prefix in `paramFormat` (for example `--`) and passed in
* `parameters` as `List[String]`.
*
* The function returns a `Map[String, String]` with extracted parameters and a `List[String]` with remaining arguments that were not extracted.
*
* If a parameter does not contain a value and is followed with another parameter (with same prefix), it is ignored.
*
* Usage:
*
* {{{
* val args = Array( "-param1", "-wrong", "generated", "singleparam1", "singleparam2", "-anotherparam", "mydata", "-param2", "myboard" )
* val (params, remaininglargs) = ParseArguments(args, List("param1", "param2"))
* }}}
*
* Results:
* {{{
* Map("param2" -> "myboard")
* Array("-wrong", "generated", "singleparam1", "singleparam2", "-anotherparam", "mydata")
* }}}
*
* @param args the input arguments
* @param parameters the parameters to be extracted from input `args`.
* @param paramFormat the param prefix to be extracted (Eg. `-` or `--`).
* @return a `Map[String,String]` with extracted params and an `Array[String]` with remaining arguments.
*/
def ParseArguments(
args: Array[String],
parameters: List[String],
paramFormat: String = "-"
): (Map[String, String], Array[String]) = {
var params: Map[String, String] = Map()
var remainingArgs = new ListBuffer[String]()
var lastKey = ""
for (key <- args.toList) {
key match {
// Below are the required module parameters
case p if parameters.contains(p.drop(paramFormat.length)) => lastKey = p.drop(paramFormat.length)
// Below are the extraction cases. No need to change.
case param if (lastKey.nonEmpty amp;amp; param.slice(0, paramFormat.length) != paramFormat) =>
params = (lastKey -> param); lastKey = ""
case param if (lastKey.nonEmpty amp;amp; param.slice(0, paramFormat.length) == paramFormat) =>
remainingArgs = param; lastKey = ""
case param if lastKey.isEmpty =>
remainingArgs = param; lastKey = ""
}
}
(params, remainingArgs.toArray)
}
}
Спекуляция:
import org.scalatest.flatspec._
import org.scalatest.matchers.should._
import Utilities._
class ParseArgumentsSpec extends AnyFlatSpec with Matchers {
"ParseArguments" should "parse one parameter" in {
val args = Array("-param1", "data1", "generated", "singleparam1")
val (params, remainingargs) = ParseArguments(args, List("param1", "param2"))
assert(params === Map("param1" -> "data1"))
assert(remainingargs === List("generated", "singleparam1"))
}
"ParseArguments" should "parse multiple parameters" in {
val args = Array("-param1", "data1", "generated", "-param2", "data2", "-anotherparam")
val (params, remainingargs) = ParseArguments(args, List("param1", "param2"))
assert(params === Map("param1" -> "data1", "param2" -> "data2"))
assert(remainingargs === List("generated", "-anotherparam"))
}
"ParseArguments" should "parse one parameter and ignore a wrong one" in {
val args = Array("-param1", "-wrong", "generated", "-anotherparam", "mydata", "-param2", "data2")
val (params, remainingargs) = ParseArguments(args, List("param1", "param2"))
assert(params === Map("param2" -> "data2"))
assert(remainingargs === List("-wrong", "generated", "-anotherparam", "mydata"))
}
"ParseArguments" should "parse one parameter with double dash('--')" in {
val args = Array("--param1", "data1", "generated", "--anotherparam", "mydata", "-param2", "data2")
val (params, remainingargs) = ParseArguments(args, List("param1", "param2"), "--")
assert(params === Map("param1" -> "data1"))
assert(remainingargs === List("generated", "--anotherparam", "mydata", "-param2", "data2"))
}
}
Комментарии:
1. Если вам нужна обратная связь по полному и рабочему коду, вы можете опубликовать ее в Обзоре кода .
2. Приятно, никогда не слышал об этом… опубликовал это, потому что это может быть полезно для других людей.