【发布时间】:2015-04-30 23:32:24
【问题描述】:
我正在从需要 3 个元素的日志中抓取信息。另一个额外的困难是我在我的 java 程序中通过 readLine() 解析日志,也就是一次 (1) 行。 (如果在解析时有可能读取多行,请告诉我:))注意:我无法控制日志输出格式。
我必须提取的内容有两种可能性。日志很好,并提供以下内容
格式不错
.text.rank 0x0000000000400b8f 0x351 is_x86.o
我必须抓住 .text.rank 、 0x0000000000400b8f 和 0x351 的地方
现在不太好的情况:如果名称太长,它会将其他所有内容撞到下一行,如下所示,现在第一个元素之后的唯一内容是一个空格,后跟一个换行符 (\n)无论如何都会被readLine() 破坏。
邪恶格式:注意每一行都在一个单独的数组列表条目中。
.text.__sfmoreglue
0x0000000000401d00 0x55 /mnt/drv2homelibc_popcorn.a(lib_a-findfp.o)
因此,正则表达式实际看到的是:
.text.__sfmoreglue
也出现在日志中但我不希望出现的 CORNER CASE FORMAT
*(.text.unlikely)
最后,下面是我目前用于第一行的 Pattern 行,pline2 是 在下一行使用的第 2 组 第一行是空的。
更新:下面的模式适用于 NICE FORMAT 和 EVIL FORMAT 但是现在模式 pline2 没有匹配项,即使在 regex101.com 上它是正确的。链接:https://regex101.com/r/vS7vZ3/9
UPDATE2: 我修复了它,我在用 Pattern pline2 编译第二行后忘记添加 m2.find()。更正的代码如下。
Pattern p = Pattern.compile("^[ \\s](\\.[tex]*\\.[\\._\\-\\@a-zA-Z0-9]*)\\s*([x0-9a-f]*)[ \\s]*([x0-9a-f]*).*");
Pattern pline2 = Pattern.compile("^\\s*([x0-9a-f]*)[ \\s]*([x0-9a-f]*)\\s*[\\w\\(\\)\\.\\-]*");
为了提供一点背景知识,我首先将名称 .text.whatever 匹配到 m.group(1),然后将地址 0x000012345 匹配到 m.group(2),最后将大小 0xa48 匹配到 m.group(3)。这一切都假设日志是 NICE 格式。如果它是 EVIL 格式,我看到 group(2) 是空的,因此将日志的下一行读入临时缓冲区并将第二个模式 pline2 应用于新行。
有人可以帮我处理正则表达式吗? 有没有办法确保我当前的行(或者更好,只是第二组)是 NICE FORMAT 还是空的?
根据要求,我的 java 代码:
//1st line pattern
Pattern p = Pattern.compile("^[ \\s](\\.[tex]*\\.[\\._\\-\\@a-zA-Z0-9]*)\\s*([x0-9a-f]*)[ \\s]*([x0-9a-f]*).*");
//conditional 2nd line pattern
Pattern pline2 = Pattern.compile("^\\s*([x0-9a-f]*)[ \\s]*([x0-9a-f]*)\\s*[\\w\\(\\)\\.\\-]*");
while((temp = br1.readLine()) != null){
Matcher m = p.matcher(temp);
while(m.find()){
System.out.println("What regex finds: m1:"+m.group(1)+"# m2:"+m.group(2)+"# m3:"+m.group(3));
if(!m.group(1).isEmpty() && m.group(2).isEmpty() && m.group(3).isEmpty()){
//means we probably hit a long symbol name and important stuff is on the next line
//save the name at least
name = m.group(1);
//read and utilize the next line
if((temp = br1.readLine()) == null){
return;
}
System.out.println("EVILline2:"+temp); //sanity check the input
System.out.println(pline2.toString()); //sanity check the regex
Matcher m2= pline2.matcher(temp);
while(m2.find()){
System.out.println("regex line2 finds: m1:"+m2.group(1));//+"# m2:"+m2.group(2));
if(m2.group(2).isEmpty()){
size = 0;
}else{
size = Long.parseLong(m2.group(2).replaceFirst("0x", ""),16);
}
addr = Long.parseLong(m2.group(1).replaceFirst("0x", ""),16);
System.out.println("#########LONG NAME: "+name+" addr:"+addr+" size:"+size);
}
}//end if
else{ // assume in NICE FORMAT
//do nice format stuff.
}//end while
}//end outerwhile
顺便说一句,我目前得到的输出:
line: .text.c_print_results
What regex finds: m1:.text.c_print_results# m2:# m3:
EVIL FORMATline2: 0x00000000004001e6 0x231 c_print_results_x86.o
^\s*([x0-9a-f]*)[ \s]*([x0-9a-f]*)\s*[\w\(\)\.\-]*
Exception in thread "main" java.lang.IllegalStateException: No match found
at java.util.regex.Matcher.group(Matcher.java:536)
at java.util.regex.Matcher.group(Matcher.java:496)
at regexTest.regex.grabSymbolsInRange(regex.java:143)
at regexTest.regex.main(regex.java:489)
【问题讨论】:
-
分离你的关注点:为好的形式创建一个正则表达式,为邪恶的形式创建一个不同的正则表达式。当你让它们都工作时,添加 a conditional 以在它们之间进行选择,基于空组 2 或行首的空白。
-
@PaulHicks 我在某种程度上按照你说的做,问题是如何在 1 个模式中容纳 2 个模式(NICE FORMAT 或名称后为空)。