我正在尝试使用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]
。
任何帮助表示赞赏。
答案 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
))