Extractor 一個(gè)特別有用的應(yīng)用是正規(guī)表達(dá)式,Scala 支持正規(guī)表達(dá)式,尤其是和 Extractor 配合使用時(shí)顯得非常便利。
Scala 繼承了 Java 的正規(guī)表達(dá)式的語(yǔ)法規(guī)則。這里我們假定你了解正規(guī)表達(dá)式。Scala 的正規(guī)表達(dá)式相關(guān)的類型定義在包 scala.util.matching 中。
創(chuàng)建一個(gè)正規(guī)表達(dá)式是使用 RegEx 類型,例如:
scala> import scala.util.matching.Regex
import scala.util.matching.Regex
scala> val Deciaml = new Regex("(-)?(\\d+)(\\.\\d*)?")
Deciaml: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
這里構(gòu)建了一個(gè)可以識(shí)別數(shù)值的正規(guī)表達(dá)式。這個(gè)表達(dá)式中使用多個(gè)\轉(zhuǎn)義,對(duì)于復(fù)雜的正規(guī)表達(dá)式來(lái)說(shuō),有時(shí)顯得太復(fù)雜,很容易出錯(cuò),Scala 允許你使用原始的正規(guī)表達(dá)式(無(wú)需轉(zhuǎn)義),這可以通過(guò)將正規(guī)表達(dá)式包含著”””字符串中,比如重寫(xiě)上面的正規(guī)表達(dá)式如下:
val Deciaml = new Regex("""(-)?(\d+)(\.\d*)?""")
此外還有一個(gè)更簡(jiǎn)潔的方法,是在字符串后使用.r 操作符,例如:
scala> val Deciaml = """(-)?(\d+)(\.\d*)?""".r
Deciaml: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
.r 為 StringOps 的方法,它把一個(gè)字符串轉(zhuǎn)換為 Regex 對(duì)象。
scala 支持下面幾種正規(guī)表達(dá)式的查找方法:
例如:
scala> val Decimal = """(-)?(\d+)(\.\d*)?""".r
Decimal: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
scala> val input = " for -1.0 to 99 by 3"
input: String = " for -1.0 to 99 by 3"
scala> for(s <- Decimal findAllIn input) println(s)
-1.0
99
3
scala> Decimal findFirstIn input
res5: Option[String] = Some(-1.0)
scala> Decimal findPrefixOf input
res6: Option[String] = None
Scala 所有定義的正規(guī)表達(dá)式都定義了一個(gè) Extractor,可以用來(lái)解析正規(guī)表達(dá)式中對(duì)應(yīng)的分組,比如前面定義的Decimal定義了三個(gè)分組,可以直接用來(lái)解析一個(gè)浮點(diǎn)數(shù):
scala> val Decimal(sign,integerpart,decimalpart) = "-1.23"
sign: String = -
integerpart: String = 1
decimalpart: String = .23
如果對(duì)應(yīng)的分組查找不到,則返回 Null,比如:
scala> val Decimal(sign,integerpart,decimalpart) = "1.0"
sign: String = null
integerpart: String = 1
decimalpart: String = .0
這種分解方法同樣可以應(yīng)用到 for 表達(dá)式中,例如:
for(Decimal(s,i,d) <- Decimal findAllIn input)
println ("sign: " +s + ",integer:" +
i + ",deciaml:" +d)
sign: -,integer:1,deciaml:.0
sign: null,integer:99,deciaml:null
sign: null,integer:3,deciaml:null