Как извлечь параметры из строки, проверенной с помощью регулярного выражения - PullRequest
1 голос
/ 30 апреля 2019

Я занимаюсь разработкой приложения, которое получает текстовые команды:

Например, текстовая команда 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")

Я не знаю, как извлечь параметры из текста.

Ответы [ 2 ]

3 голосов
/ 30 апреля 2019

Группы захвата могут использоваться для извлечения параметров

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
0 голосов
/ 01 мая 2019

Регулярное выражение из ответа @ 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, если вы хотите более гибкую грамматику.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...