Scala 补充 正则、异常处理、类型信息处理
基于前几篇文章 (Scala介绍与环境搭建、Scala 第一篇 基础篇、Scala 第二篇 算子篇、Scala 第三篇 OOP篇) 补充

(图片来源网络,侵删)
- 一、正则
- 1、匹配
- 2、替换
- 3、分割
- 4、分组
- 5、练习
- 二、异常处理
- 三、类 型信息处理
一、正则
1、匹配
-
简单匹配
// 判断content是否为数字 val content: String = "244" val regexStr: String = "\\d+" val bool = content.matches(regexStr)
- (图片来源网络,侵删)
// 将字符串 content 中的数字和逗号分隔的数字序列解析成一个三元组,如果字符串不符合指定格式则返回一个包含三个 "INVALID" 字符串的三元组。 import scala.util.matching.Regex val regex: Regex = "(\\d+),(\\d+),(\\d+)".r // r 函数:将正则字符串转化为 正则(Regex) 对象 val content: String = "12665473,33,33" val tp3: (String, String, String) = content match { case regex(g1, g2, g3) => (g1, g2, g3) case _ => ("INVALID", "INVALID", "INVALID") } println(tp3) // 输出结果:(12665473,33,33)
2、替换
replaceFirstIn 用替换字符串替换原始字符串中第一个匹配到的文本,并返回替换后的新字符串。
replaceSomeIn 对原始字符串中所有匹配到的文本进行处理,根据传入的匹配函数,选择性地进行替换或保留,并返回替换后的新字符串。
replaceAllIn 将原始字符串中所有匹配到的文本都替换为指定的替换字符串,并返回替换后的新字符串。
使用样例
val rtr = "(8\\d+)" // 匹配以数字 8 开头的连续数字序列的正则表达式模式 val regex: Regex = rtr.r // 创建正则表达式对象 val content = "java:88,mysql:80,scala:69,spark:75" // 将 content 中第一个匹配到的以数字 8 开头的连续数字序列替换为 "99" val replace1: String = regex.replaceFirstIn(content, "99") // 将 content 中所有匹配到的以数字 8 开头的连续数字序列加上 10 后替换为新的数字 // 参二为函数 f:Matcher=>Option[String] val replace2: String = regex.replaceSomeIn(content, m => Some((m.group(1).toInt + 10).toString)) // 将 content 中所有匹配到的以数字 8 开头的连续数字序列替换为 "99" val replace3: String = regex.replaceAllIn(content, "99") // 将 content 中所有匹配到的以数字 8 开头的连续数字序列加上 10 后替换为新的数字 // 参二为函数 f:Matcher=>String val replace4: String = regex.replaceAllIn(content, m => (m.group(1).toInt + 10).toString) println(replace1) println(replace2) println(replace3) println(replace4)
输出
java:99,mysql:80,scala:69,spark:75 java:98,mysql:90,scala:69,spark:75 java:99,mysql:99,scala:69,spark:75 java:98,mysql:90,scala:69,spark:75
3、分割
// 分割:将数字提取出来 val content = "11a,22b,cc33" val split: Array[String] = content.split("[^0-9]+") split.foreach(e => print(e + " ")) // 输出:11 22 33
4、分组
分组:必须添加 ()
findFirstMatchIn
findAllMatchIn
样例
val pat = "([a-z][a-zA-Z]+):(\\d+)".r val scores = "java:88,mysql:80,hadoop:84,spark:91" val option = pat.findFirstIn(scores) // 在 scores 中查找第一个匹配到的 "单词:数字" 格式的字符串,并返回一个 Option 对象 val it = pat.findAllIn(scores) // 在 scores 中查找所有匹配到的 "单词:数字" 格式的字符串,并返回一个迭代器 // it.foreach(println) // Regex.Match match = regexXxx.findXxxMatchInt(content:String) // val groupContent = match.group(id:Int) val mat = pat.findFirstMatchIn(scores) // 在 scores 中查找第一个匹配到的 "单词:数字" 格式的字符串,并返回一个 Option[Match] 对象 val mats = pat.findAllMatchIn(scores) // 在 scores 中查找所有匹配到的 "单词:数字" 格式的字符串,并返回一个迭代器[Match] 对象 mats.foreach(e => println(e.group(1) + " -> " + e.group(2))) // 分组提取
输出
java -> 88 mysql -> 80 hadoop -> 84 spark -> 91
5、练习
练习一:使用正则表达式解析日志
现有如下日志信息,请使用Scala正则表达式解析如下信息
日志级别 日期 请求URI INFO 2016-07-25 requestURI:/c?app=0&p=1&did=18005472&industry=469&adid=31 INFO 2016-07-26 requestURI:/c?app=0&p=2&did=18005473&industry=472&adid=31 INFO 2016-07-27 requestURI:/c?app=0&p=1&did=18005474&industry=488&adid=32
代码
val regex = "(INFO|WARN|ERROR) (\\d{4}-\\d{1,2}-\\d{1,2}) requestURI:(.*)".r Array( "INFO 2016-07-25 requestURI:/c?app=0&p=1&did=18005472&industry=469&adid=31", "INFO 2016-07-26 requestURI:/c?app=0&p=2&did=18005473&industry=472&adid=31", "INFO 2016-07-27 requestURI:/c?app=0&p=1&did=18005474&industry=488&adid=32" ).collect({ // collect 自带偏函数 case regex(level, date, url) => (level, date, url) }) .foreach(e=> println("level: " + e._1 + "\tdate: " + e._2 + "\turl: " + e._3))
输出
level: INFO date: 2016-07-25 url: /c?app=0&p=1&did=18005472&industry=469&adid=31 level: INFO date: 2016-07-26 url: /c?app=0&p=2&did=18005473&industry=472&adid=31 level: INFO date: 2016-07-27 url: /c?app=0&p=1&did=18005474&industry=488&adid=32
二、异常处理
-
try...catch...
import scala.util.control.Exception try { // 可能会抛出异常的代码 } catch { case e: ArithmeticException => // 处理 ArithmeticException 的代码 // 其他类型的异常处理 } finally { // 无论是否有异常发生,都会执行的代码 }
-
scala.util.control.Exception.{allCatch, failAsValue}
import scala.util.Try import scala.util.control.Exception.{allCatch, failAsValue} // 尝试执行可能会抛出异常的代码块,返回Option[Int],如果异常发生则返回None val resultOption: Option[Int] = allCatch.opt(10 / 0) // 返回Try[Int],如果异常发生则返回一个包含异常的Failure val resultTry: Try[Int] = allCatch.withTry(10 / 0) // 返回Either[Throwable, Int],如果异常发生则返回包含异常的Left val resultEither: Either[Throwable, Int] = allCatch.either(10 / 0) // 如果异常发生则返回指定的默认值 // 【推荐】参数1:异常类型,参数2:正常返回的值,参数3:异常发生返回的值 val resultWithDefaultValue: Int = failAsValue(classOf[ArithmeticException])(10 / 0)(-1)
三、类 型信息处理
classOf[] 提取类型信息
isInstanceOf[] 类型判断
asInstanceOf[] 类型转换
// Text类 case class Text(author:String,title:String,price:Float) // TextSon类 class TextSon(level:String, override val author:String, override val title:String, override val price:Float) extends Text(author, title, price) // 继承Text类 { val _level:String = level override def toString() = s"TextSon{${super.toString}, ${_level}}" }
// 提取类型信息 val ci: Class[Text] = classOf[Text] val obj:Text = new TextSon("MAX", "张三", "xxx论文", 86.32f) // 类型判断,判断obj是否为TextSon 类型 val isIns: Boolean = obj.isInstanceOf[TextSon] // true // 类型转换:转换不当会导致 ClassCastException val son: TextSon = obj.asInstanceOf[TextSon] val son: Option[TextSon] = allCatch.opt(obj.asInstanceOf[TextSon])
-