[英]Scala RDD with pattern matching from a text file
对Spark来说有点新 。 所以这是问题所在,我有一个通用格式的txt文件,可以说: Time
:
Message
因此,我必须实现两件事:RDD和模式组以及匹配。
要将文件作为rdd:
val rdd1 = sc.textFile(location)
要构建模式:
private val f1 = "([0-9]*)"
private val f2 = "([:])"
private val f3 = "(.*?)"
private val regex = s"$f1 $f2 $f3"
private val p = Pattern.compile(regex)
现在我想将这两个都整合在一起
rdd1.map(//What to do here)
我想检查每行是否与常规格式匹配。如果不行,我想为每行不匹配显示错误消息。
如果匹配,我想为上述模式分组。 f1是group1,f2是group2,f3是组3。最后,我想在f3(消息字段)中搜索诸如error,failure之类的关键字。
我知道很多事情要提前提出。
我已经尝试过的
def parseLine(s1: String): Option[Groups] = {
val matcher = p.matcher(s1)
if (matcher.find) {
println("General Format correct")
//group
Some(group(matcher))
//after format is verified search f3 for error,failure keyword.
}
else {
println("Format Wrong")
None
}
}
def group(matcher: Matcher) = {
Line(
matcher.group(1),
matcher.group(2),
matcher.group(3))}
case class Line(Time: String, colon: String, Message: String)
现在我停留在如何遍历rdd的过程中,将文本文件的每一行传递给函数。如果我将整个rdd传递给函数,即RDD [String]类型。matcher等其他元素不起作用,则导致期望字符串类型。 在阅读有关rdd函数的信息时:(如果我错了,请纠正我),foreach方法应该迭代rdd,但是我遇到类型不匹配的情况。 目前正在尝试使用map函数,但还没有。
正如我所说的,我是rdd的新手。我不知道使用分区功能是否可以帮到我而不是分组。
我真的需要经验丰富的指导。 任何帮助都适用。
对于像这样的简单示例,通常使用RDD的方式与使用简单Scala序列的方式相同。 如果将Spark排除在等式之外,则一种方法将是:
import scala.util.{Failure, Success}
val input = List(
"123 : Message1 Error",
"This line doesn't conform",
"345 : Message2",
"Neither does this one",
"789 : Message3 Error"
)
val f1 = "([0-9]*)"
val f2 = "([:])"
val f3 = "(.*)"
val regex = s"$f1 $f2 $f3".r
case class Line(a: String, b: String, c: String)
//Use Success and Failure as the functional way of representing
//operations which might not succeed
val parsed = input.map { str =>
regex.findFirstMatchIn(str).map(m => Line(m.group(1), m.group(2), m.group(3))) match {
case Some(l) => Success(l)
case None => Failure(new Exception(s"Non matching input: $str"))
}
}
//Now split the parsed result so we can handle the two types of outcome separately
val matching = parsed.filter(_.isSuccess)
val nonMatching = parsed.filter(_.isFailure)
nonMatching.foreach(println)
//Filter for only those messages we're interested in
val messagesWithError = matching.collect{
case Success(l @ Line(_,_,m)) if m.contains("Error") => l
}
messagesWithError.foreach(println)
在Spark中进行操作有何不同? 不多:
val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("Example"))
import scala.util.{Failure, Success}
val input = List(
"123 : Message1 Error",
"This line doesn't conform",
"345 : Message2",
"Neither does this one",
"789 : Message3 Error"
)
val f1 = "([0-9]*)"
val f2 = "([:])"
val f3 = "(.*)"
val regex = s"$f1 $f2 $f3".r
case class Line(a: String, b: String, c: String)
val inputRDD = sc.parallelize(input)
//Use Success and Failure as the functional way of representing
//operations which might not succeed
val parsedRDD = inputRDD.map { str =>
regex.findFirstMatchIn(str).map(m => Line(m.group(1), m.group(2), m.group(3))) match {
case Some(l) => Success(l)
case None => Failure(new Exception(s"Non matching input: $str"))
}
}
//Now split the parsed result so we can handle the two types of outcome separately
val matchingRDD = parsedRDD.filter(_.isSuccess)
val nonMatchingRDD = parsedRDD.filter(_.isFailure)
//We use collect() to bring the results back from the Spark workers to the Driver
nonMatchingRDD.collect().foreach(println)
//Filter for only those messages we're interested in
val messagesWithError = matchingRDD.collect {
case Success(l@Line(_, _, m)) if m.contains("Error") => l
}
//We use collect() to bring the results back from the Spark workers to the Driver
messagesWithError.collect().foreach(println)
}
如果结果数据集非常大,则不适合使用collect()
将结果带给驱动程序,但使用println
记录结果也不适合。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.