我很新兴。我试图从以下错误日志中提取日期和错误消息
11月11日09:44:53 www httpd [1933]:[错误] [客户端10.2.23.89](36)文件名太长
11月11日09:49:38 www httpd [2728]:[错误] [客户端10.2.23.128](36)文件名太长
11月11日10:14:23 www httpd [4530]:[错误] [客户端10.2.23.243](36)文件名太长
11月11日10:15:24 www httpd [4630]:[错误] [客户端10.2.23.42](36)文件名太长
11月11日12:05:07 www httpd [12062]:[错误] [客户端10.2.23.148](36)文件名太长
这是我在scala shell中使用的脚本
val inputfile = sc.textFile("hdfs://localhost:8020/kirthi/errorlog.txt")
val elog = inputfile.map(line => (line.substring(0, 6),line.substring(65, 83)))
elog.collect()
这是我得到的输出,但它并不像预期的那样。在所有元组中都没有完全提取消息。由于每行日志的长度不同。
Array[(String, String)] = Array((Nov 11,File name too long), (Nov 11,)File name too lon), (Nov 11,)File name too lon), (Nov 11,File name too long), (Nov 11,6)File name too lo))
但我希望输出如下所示
Array[(String, String)] = Array((Nov 11,File name too long), (Nov 11,File name too long), (Nov 11,File name too long), (Nov 11,File name too long), (Nov 11,File name too long))
如果我增加子串的长度,我就会遇到超出边界期望错误的数组。
答案 0 :(得分:1)
解析文本的一种明显方法是使用正则表达式,当然。在这种情况下,假设这些日志记录的结构总是如下:
<date: MMM dd HH:mm:ss> www httpd[<number>]: [<level>] [client <IP>] (<number>)<text>
您可以使用以下内容:
val regex = "(\\w+ \\d+) [0-9:]+ www httpd\\[\\d+\\]: \\[\\w+\\] \\[.+\\] \\(\\d+\\)(.+)$".r
匹配此结构,并将捕获日期部分和结尾处的文本,例如使用模式匹配:
val elog = inputfile.map { case regex(date, text) => (date, text) }
P.S。这不是一个Spark问题(假设您可以将集群中的所有数据收集到驱动程序应用程序中,那么Spark部分就是正确的。)