Я разрабатываю приложение, которое получает текстовые команды:
Например, текстовая команда play film ramboo first blood tv.
Во-первых, мне нужно проверить соответствие команд. Затем мне нужно извлечь из него параметры:
media = film,
name = ramboo first blood
source = tv
Для проверки соответствия я строю регулярное выражение.
Вот мое определение команды:
sealed trait WordLike {
def parameter: String
}
case class Word(parameter: String, variants: Set[String] = Set.empty) extends WordLike
case class Any(parameter: String) extends WordLike
case class CommandDef(sentence: List[WordLike]) {
private lazy val regexp = {
def acc(r: String, sentence: List[WordLike]): String = {
sentence match {
case x :: xs =>
x match {
case Word(p, variants) => acc(r + "(" + variants.mkString("|") + ")", xs)
case Any(p) => acc(r + ".*", xs)
}
case Nil => r
}
}
acc("^", sentence) + "$"
}
def `match`(text: String): Boolean = text.matches(regexp)
}
Регулярное выражение в примере выше: ^(play)(film|song).*(tv|pc)$
Я использую свой код следующим образом:
val cmd = CommandDef(List(
Word("play"),
Word("media", variants = Set("film", "music")),
Any("name"),
Word("source", variants = Set("tv", "pc"))))
cmd.`match`("play film ramboo first blood tv")
Я понятия не имею, как извлекать параметры из текста.





Группы захвата можно использовать для извлечения параметров
val pattern = """^(play) (film|song) (.*) (tv|pc)$""".r("command", "media", "name", "source")
pattern.findFirstMatchIn("play film ramboo first blood tv").foreach { m =>
println(s"media = ${m.group("media")}")
println(s"name = ${m.group("name")}")
println(s"source = ${m.group("source")}")
Выход:
media = film
name = ramboo first blood
source = tv
Регулярное выражение из ответа @olik1 хорошее, но может быть чище использовать match, чтобы разобрать его:
val CommmandPattern = """^(play) (film|song) (.*) (tv|pc)$""".r
def matchCommand(s: String) =
s match {
case CommmandPattern(command, media, name, source) =>
println(s"command=$command, nedia=$media, name=$name, source=$source")
case _ =>
println("Failed to parse command")
}
Это помещает совпадающие значения непосредственно в переменные и обеспечивает чистую обработку ошибок. Вы также можете добавить несколько шаблонов в match, если вам нужна более гибкая грамматика.