Scala正则表达式多块捕获

时间:2009-11-06 22:41:30

标签: regex scala

我正在尝试使用Scala中的正则表达式捕获多行字符串的部分内容。 输入格式为:

val input = """some text
              |begin {
              |  content to extract
              |  content to extract
              |}
              |some text
              |begin {
              |  other content to extract
              |}
              |some text""".stripMargin

我已经尝试过多种可能性,可以从begin { }块中获取文本。其中之一:

val Block = """(?s).*begin \{(.*)\}""".r

input match {
  case Block(content) => println(content)
  case _ => println("NO MATCH")
}

我得到NO MATCH。如果我删除\}正则表达式(?s).*begin \{(.*),它与最后一个块匹配,包括不需要的}和“某些文本”。我在rubular.com上检查了我的正则表达式与/.*begin \{(.*)\}/m一样,它至少匹配一个块。我想当我的Scala正则表达式匹配时,我可以开始使用findAllIn匹配所有块。我做错了什么?

我查看了Scala Regex enable Multiline option,但我无法捕获所有文本块的出现,例如Seq[String]。 任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:10)

正如Alex所说,当使用模式匹配从正则表达式中提取字段时,模式就好像它是有界的(即使用^$)。避免此问题的常用方法是首先使用findAllIn。这样:

val input = """some text
              |begin {
              |  content to extract
              |  content to extract
              |}
              |some text
              |begin {
              |  other content to extract
              |}
              |some text""".stripMargin

val Block = """(?s)begin \{(.*)\}""".r

Block findAllIn input foreach (_ match {
  case Block(content) => println(content)
  case _ => println("NO MATCH")
})

否则,您可以在开头和结尾使用.*来绕过该限制:

val Block = """(?s).*begin \{(.*)\}.*""".r

input match {
  case Block(content) => println(content)
  case _ => println("NO MATCH")
}

顺便说一下,你可能想要一个非渴望的匹配器:

val Block = """(?s)begin \{(.*?)\}""".r

Block findAllIn input foreach (_ match {
  case Block(content) => println(content)
  case _ => println("NO MATCH")
})

答案 1 :(得分:1)

在进行比赛时,我认为需要完全匹配。你的比赛相当于:

val Block = """^(?s).*begin \{(.*)\}$""".r

如果你将。*添加到最后:

val Block = """(?s).*begin \{(.*)\}.*""".r

我无法找到任何相关文档,但我遇到了同样的问题。

答案 2 :(得分:0)

作为其他答案的补充,我想指出kantan.regex的存在,它可以让你写下以下内容:

import kantan.regex.ops._

// The type parameter is the type as which to decode results,
// the value parameters are the regular expression to apply and the group to
// extract data from.
input.evalRegex[String]("""(?s)begin \{(.*?)\}""", 1).toList

这会产生:

List(Success(
  content to extract
  content to extract
), Success(
  other content to extract
))