Scala基础教程(八):模式匹配、正则表达式
匹配使用case 類:
case classes是用于模式匹配與case 表達式指定類。這些都是標準類具有特殊修飾:case。下面是一個簡單的模式使用case class匹配示例:
object Test { ?? def main(args: Array[String]) { ?? ?????? val alice = new Person("Alice", 25) ????????? ?? val bob = new Person("Bob", 32) ?? ?????? val charlie = new Person("Charlie", 32) ?? ??????for (person <- List(alice, bob, charlie)) { ???????? person match { ??????????? case Person("Alice", 25) => println("Hi Alice!") ??????????? case Person("Bob", 32) => println("Hi Bob!") ??????????? case Person(name, age) => ?????????????? println("Age: " + age + " year, name: " + name + "?") ???????? } ????? } ?? } ?? // case class, empty one. ?? case class Person(name: String, age: Int) }當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala C:/>scala Test Hi Alice! Hi Bob! Age: 32 year, name: Charlie? ? C:/>增加 case 關鍵字使編譯器自動添加了許多實用的功能。關鍵字建議與模式匹配的情況下表達式的關聯。
首先,編譯器會自動轉換的構造函數的參數為不可變的字段(vals)。val關鍵字是可選的。如果想可變字段,使用var關鍵字。因此,構造函數的參數列表現在更短。
其次,編譯器自動實現equals, hashCode, 和toString方法的類,它使用指定為構造函數參數的字段。因此,不再需要自己的toString方法。
最后,還消失Person類的主體部分,因為沒有需要定義的方法!
?
?
?
Scala支持通過Regex類的scala.util.matching封裝正則表達式。讓我們看看一個例子,我們將嘗試從Scala中一個語句中找出單詞:
import scala.util.matching.Regex ? object Test { ?? def main(args: Array[String]) { ????? val pattern = "Scala".r ????? val str = "Scala is Scalable and cool" ????? ??????println(pattern findFirstIn str) ?? } }當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala C:/>scala Test Some(Scala) ? C:/>我們創建一個字符串,并調用r()方法就可以了。Scala中字符串隱式轉換為一個RichString并調用該方法來獲得正則表達式的一個實例。找到第 一個正則表達式匹配,只需調用findFirstIn()方法。而非只找到第一次出現。如果想找到匹配的單詞的所有事件,可以使用findAllIn() 方法,并在情況下,有目標字符串中使用多個Scala的單詞,這將返回所有匹配的集合單詞。
可以使用mkString()方法來連接所產生的服務,可以使用管道(|)搜索Scala中小型和資本的情況下,使用正則表達式構造來代替或r()方法創建一個模式如下:
import scala.util.matching.Regex ? object Test { ?? def main(args: Array[String]) { ????? val pattern = new Regex("(S|s)cala") ????? val str = "Scala is scalable and cool" ????? ??????println((pattern findAllIn str).mkString(",")) ?? } }當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala C:/>scala Test Scala,scala ? C:/>如果想更換匹配的文本,可以使用replaceFirstIn()以取代第一個匹配項或replaceAllIn(),以取代所有出現如下:
object Test { ?? def main(args: Array[String]) { ????? val pattern = "(S|s)cala".r ????? val str = "Scala is scalable and cool" ????? ??????println(pattern replaceFirstIn(str, "Java")) ?? } }當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala C:/>scala Test Java is scalable and cool ? C:/>形成正則表達式:
Scala繼承了Java,這反過來又繼承了大部分的Perl的功能,它的正則表達式語法。這里只是一些例子,應該是足夠的說明:
下面是表,列出了所有的正則表達式元字符的語法可用在Java中:
| 子表達式 | 匹配 |
| ^ | 匹配行頭? |
| $ | 匹配行尾 |
| . | 匹配除換行符任何單個字符。用m選項也允許使之匹配換行符。 |
| [...] | 匹配括號內任何單個字符。 |
| [^...] | 匹配任何單個字符不是在括號中 |
| \A | 整個字符串的開始 |
| \z | 整個字符串結束 |
| \Z | 最終,除了允許的最后行結束整個字符串。 |
| re* | 匹配0或多次出現前面表達式。 |
| re+ | 匹配1個或多個的先前東西 |
| re? | 匹配0或1發生前表達式。 |
| re{ n} | 精確匹配n個前面表達式的數量。 |
| re{ n,} | 匹配n或多次出現前面的表達。 |
| re{ n, m} | 至少匹配n和在前面的表現最為m次出現。 |
| a|b | 匹配a或b。 |
| (re) | 組正則表達式并記住匹配的文本。 |
| (?: re) | 組正則表達式而不記住匹配的文本。 |
| (?> re) | 匹配獨立模式而不反向追蹤。 |
| \w | 匹配單詞字符。 |
| \W | 匹配非單詞字符。 |
| \s | 匹配空白。相當于 [ f]. |
| \S | 匹配非空白。 |
| \d | 匹配數字。相當于 [0-9]. |
| \D | 匹配非數字。 |
| \A | 匹配開始的字符串。 |
| \Z | 匹配字符串的結尾。如果一個換行符存在,它只是換行之前匹配。 |
| \z | 匹配字符串的結尾。 |
| \G | 匹配點,最后一次匹配結束。 |
| \n | 反向引用以捕獲組編號 "n" |
| \b | 匹配單詞邊界之外時,括號內。匹配退格(0×08)括號里面。 |
| \B | 匹配非單詞邊界。 |
| \n, \t, etc. | 匹配換行符,回車,制表符等 |
| \Q | 轉義(引用)所有字符為?\E |
| \E | 尾部引用開始 \Q |
正則表達式的例子:
| 示例 | 描述 |
| . | 匹配除了換行符的任何字符 |
| [Rr]uby | 匹配?"Ruby" 或"ruby" |
| rub[ye] | 匹配"ruby" 或?"rube" |
| [aeiou] | 匹配任何一個小寫元音 |
| [0-9] | 匹配任何數字;同 [0123456789] |
| [a-z] | 匹配任意小寫ASCII字母 |
| [A-Z] | 匹配任意大寫ASCII字母 |
| [a-zA-Z0-9] | 匹配任何上述 |
| [^aeiou] | 匹配元音以外的任何一個小寫字符 |
| [^0-9] | 匹配數字以外的任何其他 |
| \d | 匹配一個數字: [0-9] |
| \D | 匹配一個非數字: [^0-9] |
| \s | 匹配一個空白字符: [ f] |
| \S | 匹配非空白: [^ f] |
| \w | 匹配一個字符: [A-Za-z0-9_] |
| \W | 匹配一個非單詞字符: [^A-Za-z0-9_] |
| ruby? | 匹配 "rub" or "ruby": the y is optional |
| ruby* | 匹配 "rub" plus 0 or more ys |
| ruby+ | 匹配 "rub" plus 1 or more ys |
| \d{3} | 匹配只有?3 個數字 |
| \d{3,} | 匹配 3 個或多個數字 |
| \d{3,5} | 匹配3, 4, 或5 個數字 |
| \D\d+ | 不分組: + repeats \d |
| (\D\d)+/ | 分組: + repeats \Dd 對 |
| ([Rr]uby(, )?)+ | 匹配 "Ruby", "Ruby, ruby, ruby", 等. |
需要注意的是每一個反斜杠上述字符串中出現兩次。這是因為在Java和Scala一個反斜杠是一個轉義字符的字符串,而不是一個普通字符顯示出來的字符串。所以不是.. 需要寫.\ 。得到的字符串中的一個反斜杠。請查看下面的例子:
import scala.util.matching.Regex ? object Test { ?? def main(args: Array[String]) { ????? val pattern = new Regex("abl[ae]\d+") ????? val str = "ablaw is able1 and cool" ????? ??????println((pattern findAllIn str).mkString(",")) ?? } }當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala C:/>scala Test able1 ? C:/>?
?
Scala的異常的工作像許多其他語言,如Java異常。而不是正常方式返回的值,方法可以通過拋出一個異常終止。然而,Scala實際上并沒有檢查異常。
當要處理異常,那么可使用try{...}catch{...} 塊,就像在Java中除了catch塊采用匹配識別和處理異常。
拋出異常:
拋出一個異常看起來類似于Java。創建一個異常對象,然后使用throw關鍵字把它拋出:
throw new IllegalArgumentException捕獲異常:
Scala中try/catch在一個單獨的塊捕捉任何異常,然后使用case塊進行模式匹配,如下圖所示:
import java.io.FileReader import java.io.FileNotFoundException import java.io.IOException ? object Test { ?? def main(args: Array[String]) { ????? try { ???????? val f = new FileReader("input.txt") ????? } catch { ???????? case ex: FileNotFoundException =>{ ??????????? println("Missing file exception") ???????? } ???????? case ex: IOException => { ??????????? println("IO Exception") ???????? } ????? } ?? } }當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala C:/>scala Test Missing file exception ? C:/>這種try-catch表達的行為在其他語言處理異常是一樣的。body是執行體,如果它拋出一個異常,每個catch子句都依次嘗試捕獲。
finally子句:
如果想知道引起一些代碼是如何表達的終止執行,可以用一個finally子句包住一個表達式,finally塊什么時候都會執行。
import java.io.FileReader import java.io.FileNotFoundException import java.io.IOException ? object Test { ?? def main(args: Array[String]) { ????? try { ???????? val f = new FileReader("input.txt") ????? } catch { ???????? case ex: FileNotFoundException => { ??????????? println("Missing file exception") ???????? } ???????? case ex: IOException => { ??????????? println("IO Exception") ???????? } ????? } finally { ???????? println("Exiting finally...") ????? } ?? } }當上述代碼被編譯和執行時,它產生了以下結果:
C:/>scalac Test.scala C:/>scala Test Missing file exception Exiting finally... ? C:/>?
?
提取器在Scala中是一個對象,有一個叫非應用作為其成員的一種方法。即不應用方法的目的是要匹配的值,并把它拆開。通常,提取對象還限定了雙方法申請構建值,但是這不是必需的。
下面的例子顯示電子郵件地址的提取器對象:
object Test { ?? def main(args: Array[String]) { ????? ??????println ("Apply method : " + apply("Zara", "gmail.com")); ????? println ("Unapply method : " + unapply("Zara@gmail.com")); ????? println ("Unapply method : " + unapply("Zara Ali")); ? ?? } ?? // The injection method (optional) ?? def apply(user: String, domain: String) = { ????? user +"@"+ domain ?? } ? ?? // The extraction method (mandatory) ?? def unapply(str: String): Option[(String, String)] = { ????? val parts = str split "@" ????? if (parts.length == 2){ ???????? Some(parts(0), parts(1)) ??????}else{ ???????? None ????? } ?? } }這個對象定義了 apply 和unapply 方法。該apply 方法具有相同的含義:它原來的測試為可以被應用到的參數在括號中的方法所應用的相同的方式的對象。所以,可以寫為Test("Zara", "gmail.com") 來構造字符串“Zara@gmail.com”。
unapply方法使測試類成為一個提取器并反轉應用的構造過程。應用需要兩個字符串,并形成了一個電子郵件地址以找到它們,非應用unapply需要一個電子郵件地址,并可能返回兩個字符串:用戶和地址的域名。
unapply還必須處理中給定的字符串不是一個電子郵件地址的情況。這就是為什么unapply返回一個選項型過對字符串。其結果要么是一些(用戶域) 如果字符串str使用給定電子郵件地址的用戶和域的部分,或None,如果str不是一個電子郵件地址。下面是一些例子:
unapply("Zara@gmail.com") equals Some("Zara", "gmail.com") unapply("Zara Ali") equals None讓我們編譯和運行上面的程序,這將產生以下結果:
C:/>scalac Test.scala C:/>scala Test Apply method : Zara@gmail.com Unapply method : Some((Zara,gmail.com)) Unapply method : None ? C:/>
from: http://www.yiibai.com/scala/scala_basic_syntax.html
總結
以上是生活随笔為你收集整理的Scala基础教程(八):模式匹配、正则表达式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Scala基础教程(七):类和对象、特征
- 下一篇: Scala基础教程(九):提取器、文件I