我正在使用日志分析工具。
我在hadoop中使用yarn日志聚合函数。当我这样做的时候,hadoop日志文件非常大,以至于一些api方法无法将文件的内容完全读取到内存中。
我想在第一行包含字符串的文件中匹配多行块 [map]
最后一行包含 [\map]
-我想我可以用正则表达式来做这个。常用的 BufferedReader
不能满足我的要求。
我的问题是:是否有其他方法逐行检查文件,检查那些与我的regex匹配的文件?
p、 我真的不想分割成多个较小的文件来处理,因为我担心这会导致一些匹配的内容找不到,因为我可能会分割在一个匹配块的中间文件。
下面是日志文件的片段-我想要 [MAP]
以及 [/MAP]
:
2015-04-16 20:30:09,240 INFO [main] org.apache.hadoop.hive.ql.exec.MapOperator: dump TS struct
2015-04-16 20:30:09,240 INFO [main] org.apache.hadoop.hive.ql.exec.mr.ExecMapper:
[MAP]Id =4
[Children]
[TS]Id =2
[Children]
[RS]Id =3
[Parent]Id = 2 null[\Parent]
[\RS]
[\Children]
[Parent>Id = 4 null[\Parent]
[\TS]
[\Children]
[\MAP]
2015-04-16 20:30:09,241 INFO [main] org.apache.hadoop.hive.ql.exec.MapOperator: Initializing Self 4 MAP
2015-04-16 20:30:09,242 INFO [main] org.apache.hadoop.hive.ql.exec.TableScanOperator: Initializing Self 2 TS
2015-04-16 20:30:09,242 INFO [main] org.apache.hadoop.hive.ql.exec.TableScanOperator: Operator 2 TS initialized
2条答案
按热度按时间um6iljoc1#
n、 b.根据评论中的澄清进行编辑
使用regex可以找到你的多行块-你当然可以写一个regex来匹配它们。
.*\[MAP\]((?s).*)\[\\MAP\]
-注意,在java中,还必须避开所有\
人物之类的(?s)
允许.
匹配换行符的字符,即。但是,正如您所强调的,如果文件无法放入内存,则会产生困难,拆分它也会有一些困难。
我将提出一个不同的想法-逐行扫描文件,并使用状态变量来指示是否在块中。基本算法如下
匹配块的开头时,将状态变量设置为true。
当state为true时,将文本附加到
StringBuilder
匹配块的结尾时,将状态变量设置为false并使用String
你已经建立了,例如,输出到文件,到控制台或使用它的编程。java解决方案
我将建议一种实现上述功能的方法—使用
Scanner
-它一行一行地穿过一条溪流,沿途丢弃它们,从而避免OutOfMemoryError
. 注意这个代码可以抛出异常-我已经抛出了它们,但是您可以将它们放入try..catch..finally
阻止。还要注意的是Scanner
吞咽io异常,但正如医生所说,如果这对你很重要:可以通过ioexception()方法检索基础readable函数抛出的最新ioexception。
警告:您的文件可能有一些特性,如果不进行一些修改,这些特性将无法工作。如果可以嵌套
[map]
那么是街区inBlock
需要是一个int,如果匹配块开始,则递增,如果匹配结束,则递减-对于任何inblock > 0
只有在inBlock
归零。命令行拆分,在单行上查找匹配项
如果您是在每行的基础上搜索,并且匹配项保证在一行上,那么只要分割只发生在完整行的末尾,分割就可以了。
在这种情况下,可以使用命令行拆分文件。如果您使用的是linux(或者,我认为,任何*nix),那么可以使用split命令,例如。
在这个问答中有更多的细节
在windows上,我知道没有一个等效的命令,但是您可以安装类似的命令,例如gnucoreutils for windows或7-zip。注意:我从来没有用过这些来分裂。
inkz8wg92#
您可以使用javanio包来代替缓冲读取器,这与缓冲读取器相比非常快