regex - 如何创建通用正则表达式,以便可以在 scala spark 中提取所有组结果
问题描述
我们有 .txt 日志文件,我使用 scala spark 读取文件。该文件包含按行排列的数据集。我一一读取数据,如下所示
val sc = spark.SparkContext
val dataframe = sc.textFile(/path/to/log/*.txt)
主要是所有日志文件中的数据是三种类型,如下所示
ManagedElement=LNJ05193B,ENodeBFunction=1,RadioBearerTable=default,DataRadioBearer=1 dlMaxRetxThreshold 8 LNJ05193B dlMaxRetxThreshold 8
ManagedElement=LNJ05024D,ENodeBFunction=1,EUtranCellFDD=DNJ05024D31 enableServiceSpecificHARQ false DNJ05024D31 enableServiceSpecificHARQ FALSE
ManagedElement=LNJ05024D,ENodeBFunction=1,EUtranCellFDD=LNJ05024D31 primaryUpperLayerInd OFF LNJ05024D31 primaryUpperLayerInd OFF
第二种类型的线是这种类型
ManagedElement=LNJ05024D,ENodeBFunction=1,EUtranCellFDD=BNJ05024D31,EUtranFreqRelation=5035 connectedModeMobilityPrio 7 LNJ05024D 5035 connectedModeMobilityPrio
一些原始行如下:
ManagedElement=LNJ05147D,ENodeBFunction=1,EUtranCellFDD=LNJ05147D11,EUtranFreqRelation=2250,EUtranCellRelation=310260-51992-1 cellIndividualOffsetEUtran 0 LNJ05147D11 2250 310260 cellIndividualOffsetEUtran 0
我尝试制作一个包含上述所有记录的通用 csv 文件,如下所示
在所有类型的行中,共同的部分是 Mana= 和 ENF= 所以要得到它,使用正则表达式,如
val regx_first_exp = """"Manag=(\w*).*ENF=(\w),.*""".r
最后两个词是关键值,可以像下面这样提取
val last_two = """(\w+)=(\w+[^=])"""".r
在这两者之间,我尝试在不同的 eqal to( =sign) 之后提取值,并且如果没有匹配项,则希望将其放入不同的列中,而不是在特定列中简单地放置空值。
最终结果如下:
+--------------+-----------+---------------+--------------+--------------------------+----------+
|managedElement|cellFDD |targetFrequency|targetCell |paramName |paramValue|
+--------------+-----------+---------------+--------------+--------------------------+----------+
|LNJ05025D |DNJ05025D31|AWS_2087 |null |threshXHighQ |0 |
|LNJ05024D |BNJ05024D31|5035 |null |connectedModeMobilityPrio |7 |
|LNJ05193B |null |null |null |dlMaxRetxThreshold |8 |
|LNJ05024D |DNJ05024D31|null |null |enableServiceSpecificHARQ |false |
|LNJ05024D |LNJ05024D31|null |null |primaryUpperLayerInd |OFF |
|LNJ05147D |LNJ05147D11|2250 |310260-51992-1|cellIndividualOffsetEUtran|0 |
+--------------+-----------+---------------+--------------+--------------------------+----------+
这是否可以在单个正则表达式或多个 udf 函数中与最小过滤器一样多?
我是scala的新手,请提供相同的建议。图像中的最后一列仅用于一一提到的行类型。
解决方案
这是一种使用与正则表达式进行模式匹配的 4 个不同正则表达式的解决方案,如下所述:
val df = Seq(
("ManagedElement=LNJ05025D,ENodeBFunction=1,EUtranCellFDD=DNJ05025D31,UtranFreqRelation=AWS_2087 threshXHighQ 0"),
("ManagedElement=LNJ05024D,ENodeBFunction=1,EUtranCellFDD=BNJ05024D31,EUtranFreqRelation=5035 connectedModeMobilityPrio 7"),
("ManagedElement=LNJ05193B,ENodeBFunction=1,RadioBearerTable=default,DataRadioBearer=1 dlMaxRetxThreshold 8"),
("ManagedElement=LNJ05024D,ENodeBFunction=1,EUtranCellFDD=DNJ05024D31 enableServiceSpecificHARQ false"),
("ManagedElement=LNJ05024D,ENodeBFunction=1,EUtranCellFDD=LNJ05024D31 primaryUpperLayerInd OFF"),
("ManagedElement=LNJ05147D,ENodeBFunction=1,EUtranCellFDD=LNJ05147D11,EUtranFreqRelation=2250,EUtranCellRelation=310260-51992-1 cellIndividualOffsetEUtran 0")
).toDF("logs")
case class LogItem(managedElement: String, cellFDD: String, targetFrequency: String, targetCell: String, paramName: String, paramValue: String)
// 1st type: ManagedElement=LNJ05025D,ENodeBFunction=1,EUtranCellFDD=DNJ05025D31,UtranFreqRelation=AWS_2087 threshXHighQ 0
// extract 5 groups
val log1RegExpr = """^ManagedElement=(\w+).*EUtranCellFDD=(\w+).*tranFreqRelation=(\w+)\s(\w+)\s(\w+)$""".r
// 2nd type: ManagedElement=LNJ05193B,ENodeBFunction=1,RadioBearerTable=default,DataRadioBearer=1 dlMaxRetxThreshold 8
// extract 3 groups
val log2RegExpr = """^ManagedElement=(\w+).*\s(\w+)\s(\w+)$""".r
// 3rd type: ManagedElement=LNJ05024D,ENodeBFunction=1,EUtranCellFDD=DNJ05024D31 enableServiceSpecificHARQ false
// extract 4 groups
val log3RegExpr = """^ManagedElement=(\w+).*EUtranCellFDD=(\w+)\s(\w+)\s(\w+)$""".r
// 4th type: ManagedElement=LNJ05147D,ENodeBFunction=1,EUtranCellFDD=LNJ05147D11,EUtranFreqRelation=2250,EUtranCellRelation=310260-51992-1 cellIndividualOffsetEUtran 0
// extract 6 groups
val log4RegExpr = """^ManagedElement=(\w+).*EUtranCellFDD=(\w+).*tranFreqRelation=(\w+).*EUtranCellRelation=(\S+)\s(\w+)\s(\w+)$""".r
df.map{row =>
row.getString(0) match {
case log4RegExpr(me, cf, tf, tc, pn, pv) => LogItem(me, cf, tf, tc, pn, pv)
case log1RegExpr(me, cf, tf, pn, pv) => LogItem(me, cf, tf, null, pn, pv)
case log3RegExpr(me, cf, pn, pv) => LogItem(me, cf, null, null, pn, pv)
case log2RegExpr(me, pn, pv) => LogItem(me, null, null, null, pn, pv)
case _ => throw new Exception("Invalid format")
}
}.show(false)
和输出:
+--------------+-----------+---------------+--------------+--------------------------+----------+
|managedElement|cellFDD |targetFrequency|targetCell |paramName |paramValue|
+--------------+-----------+---------------+--------------+--------------------------+----------+
|LNJ05025D |DNJ05025D31|AWS_2087 |null |threshXHighQ |0 |
|LNJ05024D |BNJ05024D31|5035 |null |connectedModeMobilityPrio |7 |
|LNJ05193B |null |null |null |dlMaxRetxThreshold |8 |
|LNJ05024D |DNJ05024D31|null |null |enableServiceSpecificHARQ |false |
|LNJ05024D |LNJ05024D31|null |null |primaryUpperLayerInd |OFF |
|LNJ05147D |LNJ05147D11|2250 |310260-51992-1|cellIndividualOffsetEUtran|0 |
+--------------+-----------+---------------+--------------+--------------------------+----------+
如您所见,我们在匹配给定表达式之一后返回案例类 LogItem 的实例。
这里需要注意两点:
您应该小心地保持上面指定的匹配情况的顺序,从较大(要提取更多匹配项)到较小(较少匹配项),否则 log4 可能属于 log2 类别,因为仍有匹配项!
从您的示例看来, EUtranCellRelation 包含特殊字符,因此
\S+
需要(非空格字符)而不是\w
.
推荐阅读
- php - 数组中的查找键在存在时找不到文本
- go - 如何在 Go/Golang 中使用 map[string]string 或自定义结构?
- docker - docker-compose:找不到命令詹金斯管道
- android - 如何使用子片段管理 Backstack?
- single-sign-on - 使用 Google-Account 登录 Alfresco
- javascript - 在 Grape Js 中为子元素添加属性?
- linux - 在 Linux 系统调用序列中区分 execve() 的解释器
- swift - Swift 4 正则表达式自定义验证
- c# - 针对以“flashplayer”或“flashplayer_X_sa”开头的所有进程名称
- r - 时空中的随机点