程式扎記: [Scala 小學堂] Scala Gossic : 繼續深入 - 提取器 (規則表示式與提取器)

標籤

2016年7月22日 星期五

[Scala 小學堂] Scala Gossic : 繼續深入 - 提取器 (規則表示式與提取器)

Source From Here 
規則表示式與提取器 
Scala 使用與 Java 相同的規則表示式(Regular Expression)語法,你可以在 java.util.regex.Pattern 找到語法說明。以下先介紹幾個簡單的正則表示式。一些常用的範圍,可以使用預先定義的字元類別: 



. 符合任一字元。例如有一字串 abcdebcadxbc,使用 .bc 來比對的話,符合的子字串有 abc、ebc、xbc 三個;如果使用 ..cd,則符合的子 字串只有 abcd。以上的例子來根據字元比對,也可以使用「字元類」(Character class)來比較一組字元範圍,例如: 


可以用 Greedy quantifiers 來 指定字元可能出現的次數: 


字串物件擁有 matches() 方法可以讓您驗證字串是否符合指定的規則表示式,這通常用於驗證使用者輸入的字串資料是否正確,例如電話號碼格式; replaceAll() 方法可以將符合規則表示式的子字串置換為指定的字串;split() 方法可以依指定的規則表示式,將符合的子字串分離出來,並以 字串陣列傳回。在 Scala 中若要建立可重複使用的規則表示式物件,可使用 scala.util.matching.Regex 類別,例如: 

  1. import scala.util.matching.Regex  
  2. val yp = new Regex("\\d\\d\\d\\d")  
  3.   
  4. val year = yp.findFirstIn("Birthday: 1975/05/26")  
  5. println(year.getOrElse("沒有年份資訊"))   // 1975  
如果你在 " 與 " 間定義規則表示式,那麼對於 \d 的第一個 \ 字元,你必須避開(Escape),也就是寫為 \\d 的形式,如果你不想特意作避開字元的動作,則可以在 """ 與 """ 定義規則表示式,例如: 
  1. import scala.util.matching.Regex  
  2. val yp = new Regex("""\d\d\d\d/\d\d/\d\d""")  
  3.   
  4. val year = yp.findFirstIn("Birthday: 1975/05/26")  
  5. println(year.getOrElse("沒有年份資訊"))   // 1975/05/26  
事實上,你可以更簡便地利用 scala.collection.immutable.StringOpts 的 r 方法來建立規則表示式: 
scala> val yp = """(\d\d\d\d)/(\d\d)/(\d\d)""".r
yp: scala.util.matching.Regex = (\d\d\d\d)/(\d\d)/(\d\d)

scala> val year = yp.findFirstIn("Birthday: 1980/07/31")
year: Option[String] = Some(1980/07/31)

scala> year.getOrElse("Missing")
res9: String = 1980/07/31

當你使用 () 將規則表示式中某些規則群組起來時,你可以運用 提取器 的語法來提取符合的元素,例如: 
  1. val Birthday = """(\d\d\d\d)/(\d\d)/(\d\d)""".r  
  2. val Birthday(y, m, d) = "1975/05/26"  
  3. printf("%s 年 %s 月 %s 日%n", y, m, d)  // 1975 年 05 月 26 日  
如果 () 被設定為可出現零次的情況,若要比對的字串沒有出現,則提取出 null 值,例如: 
scala> val Birthday = """(\d\d\d\d)/(\d\d)/(\d\d)""".r
Birthday: scala.util.matching.Regex = (\d\d\d\d)/(\d\d)/(\d\d)

scala> val Birthday(y, m, d) = "1980/7/31" // Mismatch will throw scala.MatchError
scala.MatchError: 1980/7/31 (of class java.lang.String)
... 32 elided


scala> val Birthday(y, m, d) = "1980/07/31"
y: String = 1980
m: String = 07
d: String = 31


scala> val Birthday(y, m, d) = "07/31"
scala.MatchError: 07/31 (of class java.lang.String)
... 32 elided


scala> val Birthday = """(\d\d\d\d)?/?(\d\d)/(\d\d)""".r
Birthday: scala.util.matching.Regex = (\d\d\d\d)?/?(\d\d)/(\d\d)

scala> val Birthday(y, m, d) = "07/31"
y: String = null
m: String = 07
d: String = 31

之所以可以使用這樣的提取器語法,是因為 scala.util.matching.Regex 類別定義了 unapplySeq() 方法,對於符合規則表示式中使用 () 群組的部份提取出來。

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!