當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Scala matching.Regex用法及代碼示例


@SerialVersionUID (-2094783597747625537L)

用法 一

class Regex extends Serializable

正則表達式用於確定字符串是否與模式匹配,如果匹配,則提取或轉換匹配的部分。

用法

此類委托給 Java 平台的 java.util.regex 包。有關模式字符串的正則表達式語法的詳細信息,請參閱java.util.regex.Pattern 的文檔。

Regex 的實例表示已編譯的正則表達式模式。由於編譯成本高昂,因此經常使用的Regex es 應該在循環之外構建一次,並且可能在伴隨對象中構建。

創建 Regex 的規範方法是使用為字符串隱式提供的方法 r

val date = raw"(\d{4})-(\d{2})-(\d{2})".r

由於在多行字符串文字中不處理轉義,因此使用三引號避免了必須轉義反斜杠字符,因此 "\\d" 可以寫成 """\d""" 。使用某些插值器可以實現相同的結果,例如 raw"\d".r 或同時編譯 Regex 的自定義插值器 r"\d"

萃取

要在匹配 Regex 時提取捕獲組,請將其用作模式匹配中的提取器:

"2004-01-20" match {
  case date(year, month, day) => s"$year was a good year for PLs."
}

要僅檢查 Regex 是否匹配,忽略任何組,請使用序列通配符:

"2004-01-20" match {
  case date(_*) => "It's a date!"
}

這是有效的,因為 Regex 提取器會生成一係列字符串。僅從日期中提取年份也可以用序列通配符表示:

"2004-01-20" match {
  case date(year, _*) => s"$year was a good year for PLs."
}

在模式匹配中,Regex 通常匹配整個輸入。但是,未錨定的 Regex 會在輸入中的任何位置找到該模式。

val embeddedDate = date.unanchored
"Date: 2004-01-20 17:25:18 GMT (10 years, 28 weeks, 5 days, 17 hours and 51 minutes ago)" match {
  case embeddedDate("2004", "01", "20") => "A Scala is born."
}

查找匹配項

要查找或替換模式的匹配項,請使用各種查找和替換方法。對於每種方法,都有一個用於處理匹配字符串的版本和另一個用於處理Match 對象的版本。

例如,與前麵的示例一樣,與未錨定的 Regex 的模式匹配也可以使用 findFirstMatchIn 來完成。 findFirst 方法返回一個 Option 如果找到匹配項則為非空,如果沒有匹配項則返回 None

val dates = "Important dates in history: 2004-01-20, 1958-09-05, 2010-10-06, 2011-07-15"
val firstDate = date.findFirstIn(dates).getOrElse("No date found.")
val firstYear = for (m <- date.findFirstMatchIn(dates)) yield m.group(1)

要查找所有匹配項:

val allYears = for (m <- date.findAllMatchIn(dates)) yield m.group(1)

要檢查輸入是否與正則表達式匹配:

date.matches("2018-03-01")                     // true
date.matches("Today is 2018-03-01")            // false
date.unanchored.matches("Today is 2018-03-01") // true

要遍曆匹配的字符串,請使用 findAllIn ,它返回一個特殊的迭代器,可以查詢最後一個匹配的 MatchData

val mi = date.findAllIn(dates)
while (mi.hasNext) {
  val d = mi.next
  if (mi.group(1).toInt < 1960) println(s"$d: An oldie but goodie.")
}

盡管 findAllIn 返回的 MatchIterator 與任何 Iterator 一樣使用,交替調用 hasNextnext ,但 hasNext 具有將底層匹配器推進到下一個未使用匹配的附加副作用。此效果在代表"current match" 的MatchData 中可見。

val r = "(ab+c)".r
val s = "xxxabcyyyabbczzz"
r.findAllIn(s).start    // 3
val mi = r.findAllIn(s)
mi.hasNext              // true
mi.start                // 3
mi.next()               // "abc"
mi.start                // 3
mi.hasNext              // true
mi.start                // 9
mi.next()               // "abbc"

該示例顯示 MatchData 上的方法(例如 start)將在必要時前進到第一個匹配項。如果next 已經返回當前匹配,它還顯示hasNext 將前進到下一個未使用的匹配。

當前的MatchData 可以使用matchData 方法捕獲。或者,findAllMatchIn 返回一個 Iterator[Match] ,其中迭代器和它已經生成的 Match 對象之間沒有交互。

請注意,findAllIn 會查找不重疊的匹配項。 (有關更多示例,請參閱findAllIn。)

val num = raw"(\d+)".r
val all = num.findAllIn("123").toList  // List("123"), not List("123", "23", "3")

替換文本

文本替換可以無條件執行,也可以根據當前匹配執行:

val redacted    = date.replaceAllIn(dates, "XXXX-XX-XX")
val yearsOnly   = date.replaceAllIn(dates, m => m.group(1))
val months      = (0 to 11).map { i => val c = Calendar.getInstance; c.set(2014, i, 1); f"$c%tb" }
val reformatted = date.replaceAllIn(dates, _ match { case date(y,m,d) => f"${months(m.toInt - 1)} $d, $y" })

Match 與創建它的 Regex 匹配的模式不會重新應用 Regex 。在 reformatted 的表達式中,每個 date 匹配計算一次。但是可以將 Regex 應用於由不同模式產生的 Match

val docSpree = """2011(?:-\d{2}){2}""".r
val docView  = date.replaceAllIn(dates, _ match {
  case docSpree() => "Historic doc spree!"
  case _          => "Something else happened"
})

值參數:

groupNames

捕獲組中從名稱到索引的映射

pattern

編譯的模式

也可以看看:

伴生:

object

源碼:

Regex.scala

用法 二

object Regex

該對象定義了說明正則表達式匹配和輔助對象的內部類。

伴生:

class

源碼:

Regex.scala

相關用法


注:本文由純淨天空篩選整理自scala-lang.org大神的英文原創作品 matching.Regex。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。