使用正则表达式的Scala捕获组


73

假设我有以下代码:

val string = "one493two483three"
val pattern = """two(\d+)three""".r
pattern.findAllIn(string).foreach(println)

我希望findAllIn只返回483,但是它返回了two483three。我知道我只能unapply提取那一部分,但是我必须为整个字符串设置一个模式,例如:

 val pattern = """one.*two(\d+)three""".r
 val pattern(aMatch) = string
 println(aMatch) // prints 483

是否有另一种方法可以实现,而不必java.util直接使用类,也可以不使用unapply?

Answers:


106

这是如何访问group(1)每个匹配项的示例:

val string = "one493two483three"
val pattern = """two(\d+)three""".r
pattern.findAllIn(string).matchData foreach {
   m => println(m.group(1))
}

打印"483"如ideone.com上所示)。


环视选项

根据模式的复杂性,您还可以使用环视效果匹配所需的部分。它看起来像这样:

val string = "one493two483three"
val pattern = """(?<=two)\d+(?=three)""".r
pattern.findAllIn(string).foreach(println)

上面也打印"483"如ideone.com上所示)。

参考文献


1
您也可以pattern.findAllMatchIn(string).foreach...改用
ruhong

37
val string = "one493two483three"
val pattern = """.*two(\d+)three.*""".r

string match {
  case pattern(a483) => println(a483) //matched group(1) assigned to variable a483
  case _ => // no match
}

5
到目前为止,这是最简单的方法。您在匹配项/案例中使用正则表达式对象(“模式”)并将该组提取到变量a483中。这种情况的问题在于,模式两边都应该有通配符:val pattern =“”“。* two(\ d +)three。*”“”。r
makethematrix

是。我不认为上面的内容是立即明白的,但是一旦您了解到它会将数字匹配组分配给变量“ a483”,那么它就更有意义了。也许以更清晰的方式重写?
Brian Agnew

1
这是使用正则表达式的scala方式。对于人不明白这个答案背后的魔法,尝试搜索“正则表达式阶提取器”或“取消套用阶正则表达式”等等
JasonWayne

语义尚不清楚。这是字符串的第一个,最后一个还是随机匹配?
user239558

16

您要查看group(1),当前正在查看group(0),它是“整个匹配的字符串”。

请参阅此正则表达式教程


1
你能说明我提供的输入吗?我试图调用group(1)findAllIn返回的内容,但收到IllegalStateException。
地理位置

15

从开始Scala 2.13,作为正则表达式解决方案的替代方案,也可以String通过不应用字符串插值器来对a进行模式匹配:

"one493two483three" match { case s"${x}two${y}three" => y }
// String = "483"

甚至:

val s"${x}two${y}three" = "one493two483three"
// x: String = one493
// y: String = 483

如果期望输入不匹配,则可以添加默认的模式防护:

"one493deux483three" match {
  case s"${x}two${y}three" => y
  case _                   => "no match"
}
// String = "no match"

3
def extractFileNameFromHttpFilePathExpression(expr: String) = {
//define regex
val regex = "http4.*\\/(\\w+.(xlsx|xls|zip))$".r
// findFirstMatchIn/findAllMatchIn returns Option[Match] and Match has methods to access capture groups.
regex.findFirstMatchIn(expr) match {
  case Some(i) => i.group(1)
  case None => "regex_error"
}
}
extractFileNameFromHttpFilePathExpression(
    "http4://testing.bbmkl.com/document/sth1234.zip")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.