【问题标题】:Regex expression for multiple patterns in 1 line1 行中多个模式的正则表达式
【发布时间】:2015-04-30 23:32:24
【问题描述】:

我正在从需要 3 个元素的日志中抓取信息。另一个额外的困难是我在我的 java 程序中通过 readLine() 解析日志,也就是一次 (1) 行。 (如果在解析时有可能读取多行,请告诉我:))注意:我无法控制日志输出格式。

我必须提取的内容有两种可能性。日志很好,并提供以下内容

格式不错

.text.rank     0x0000000000400b8f      0x351 is_x86.o

我必须抓住 .text.rank0x0000000000400b8f0x351 的地方

现在不太好的情况:如果名称太长,它会将其他所有内容撞到下一行,如下所示,现在第一个元素之后的唯一内容是一个空格,后跟一个换行符 (\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 FORMATEVIL 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 或名称后为空)。

标签: java regex string parsing


【解决方案1】:

您的模式存在一些问题。

  • 1st 是第一组和第二组的分离(这就是第 2 组返回 null 的原因)。
  • 你有 4 个组,你需要 3 个
  • 捕获 3 个值后,您可以停止匹配,因此在 最后一组不是必需的
  • 您需要全局修饰符 \g 以便返回所有匹配项

因此,您可以尝试使用发布的 Regex,而不是:

(\\.[tex]*\\.[\\._\\-\\@a-zA-Z0-9]*)\\s*([x0-9a-f]*)[ \\s]+([x0-9a-f]*)/g

在 Regex101.com 上测试:

https://regex101.com/r/lM4bQ9/1

除此之外,还有一些建议:

  • 如果您知道您的文本将以文本开头,只需将其放在 模式,不要使用 [tex]*,这将需要一些额外的工作 引擎。
  • [ \s] 与 \s 相同。
  • [\._\-\@a-zA-Z0-9]* 据我了解,基本上是 除了空间,为什么不直接使用 [^\s]*

因此,考虑到这些,我建议您改用这种模式:

(\\.text\\.[^\\s]*)\\s*([x0-9a-f]*)\\s+([x0-9a-f]*)/g

【讨论】:

  • 首先,再次感谢您的及时回复!如果我使用您的第一个输入模式,则没有任何内容与我的日志匹配,但我同意您的解决方案看起来是正确的。我还简化了问题的 [tex]*,因为我还在寻找其他起始词。我在我的编码中是明确的,而不是简化为一个健全的检查。
  • 发布你的java代码,也许正则表达式不是问题,它应该匹配,因为它在测试工具中匹配
  • 我已经更新了问题以包含我的 Java 代码,并且还更新了我的最新模式。仅供参考,我确实稍微调整了你的模式,以摆脱我遇到的一个角落案例。只是重申模式 p 现在有效,但模式 pline2 无效。
  • 发现错误!我忘了为第二行模式再次调用 m.find() !我一放进去,它就在报废信息。再次感谢您查看我的问题!
  • 我很高兴能以某种方式帮助你,伙计,干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
  • 2017-10-08
  • 1970-01-01
  • 2019-10-23
  • 1970-01-01
相关资源
最近更新 更多