解析一组文本以匹配两个正则表达式的最有效方法?

时间:2017-05-09 17:21:07

标签: java regex

我是Java的新手,想要了解我在做什么。有没有更有效的方法来编程?我在connectionInfo中有一个文本正文,我闯入线条来解析匹配器。我可以从connectionInfo检索匹配的文本而不将其分成行吗?这是匹配两个字符串的有效方法吗?我需要为此创建两个单独的Matcher对象吗?

// Parse rid and rtoe (estimated time to completion)
String rid = null;
String rtoe = null;
Pattern ridPattern = Pattern.compile("RID = (.*$)");
Pattern rtoePattern = Pattern.compile("RTOE = (.*$)");
Matcher ridMatcher;
Matcher rtoeMatcher;

String[] lines = connectionInfo[0].split("\n");
for (String line : lines) {
    ridMatcher = ridPattern.matcher(line);
    rtoeMatcher = rtoePattern.matcher(line);
    if (ridMatcher.find()) {
        rid = ridMatcher.group(1);
    }
    if (rtoeMatcher.find()) {
        rtoe = rtoeMatcher.group(1);
    }
}

System.out.println("Request ID: " + rid);
System.out.println("Estimated time to completion: " + rtoe + " seconds");

2 个答案:

答案 0 :(得分:1)

  

我是否可以在没有connectionInfo的情况下检索匹配的文字   把它分成几行?

您可以匹配包含换行符的输入字符串,因此从这个意义上说,是的。要使$锚点在行终止符之前匹配,除了输入结尾之外,您还需要使用MULTILINE选项编译模式,或者将其直接放入模式中。默认情况下.元字符与新行不匹配(尽管有一个选项),因此您不必担心跨越多行的捕获组。

  

这是匹配两个字符串的有效方法吗?

跳过行拆分和迭代并且只匹配每个模式一次会更有效。然后检测一个或两个在任何地方都不匹配的错误条件也会更方便:

Pattern ridPattern = Pattern.compile("RID = (.*)$", Pattern.MULTILINE);
Pattern rtoePattern = Pattern.compile("RTOE = (.*)$", Pattern.MULTILINE);
Matcher ridMatcher = ridPattern.matcher(connectionInfo[0]);
Matcher rtoeMatcher = rtoePattern.matcher(connectionInfo[0]);

if (ridMatcher.find()) {
    rid = ridMatcher.group(1);
}  // else error: no RID
if (rtoeMatcher.find()) {
    rtoe = rtoeMatcher.group(1);
}  // else error: no RTOE

System.out.println("Request ID: " + rid);
System.out.println("Estimated time to completion: " + rtoe + " seconds");
  

我是否需要为此创建两个单独的Matcher对象?

Matcher特定于特定的Pattern,因此,对于您提供的Pattern,是的,您需要两个Matcher。这可能不是什么值得担心的问题,但是如果所提供的代码运行得如此频繁以至于产生的垃圾的性能或数量是一个真正的问题,那么有一些方法可以缓解它:

  • 仅为整个班级编译一次Pattern,将其记录在静态字段中。模式编译相对昂贵,如果您的代码是瓶颈,这可能是一个重大的胜利。

  • 当且仅当该方法受到并发调用的保护时,为每个模式创建一个Matcher,同样记录在静态字段中,并根据需要将它们绑定到每个新输入的一个arg reset()方法。这将减少产生的垃圾量,但如果这种方法对GC的巨大问题做出了重大贡献,那么这是值得的。

答案 1 :(得分:0)

你正在寻找一个好的解决方案,但是你可以调整一些小的东西来改善它。

matcher.group(1)如果找不到模式将返回null,因此我们不需要检查并确保它会找到它(因为无论如何你都是从null开始) 。你纠正了我们不需要两个匹配器。

// Parse rid and rtoe (estimated time to completion)
String rid = null;
String rtoe = null;
Pattern ridPattern = Pattern.compile("RID = (.*$)");
Pattern rtoePattern = Pattern.compile("RTOE = (.*$)");

String[] lines = connectionInfo[0].split("\n");
for (String line : lines) {
    Matcher patternMatcher = ridPattern.matcher(line);
    rid = patternMatcher.group(1);
    patternMatcher = rtoePattern.matcher(line);
    rtoe = patternMatcher.group(1);
}

System.out.println("Request ID: " + rid);
System.out.println("Estimated time to completion: " + rtoe + " seconds");

但是,您可能会注意到for循环中有一些重复的代码。一般来说,这是一个坏主意。我们可以做的是制作一个小帮助方法来处理这个逻辑:

private static String getGroupFromPattern( Pattern pattern, String line ) {
    Matcher patternMatcher = pattern.matcher(line);
    return patternMatcher.group(1);
}

然后你的原始逻辑将成为:

// Parse rid and rtoe (estimated time to completion)
String rid = null;
String rtoe = null;
Pattern ridPattern = Pattern.compile("RID = (.*$)");
Pattern rtoePattern = Pattern.compile("RTOE = (.*$)");

String[] lines = connectionInfo[0].split("\n");
for (String line : lines) {
    rid = getGroupFromPattern(ridPattern, line);
    rtoe = getGroupFromPattern(rtoePattern, line);
}

System.out.println("Request ID: " + rid);
System.out.println("Estimated time to completion: " + rtoe + " seconds");

我们也可能只使用一个Pattern对象,但我喜欢你原来的方式。只是因为它更容易阅读然后一些String引用正在提供模式。希望这有帮助!

最后一个注意事项:你使用的是想要使用matcher.group(1)吗?这将为您提供第二个分组,而不是第一个分组。如果你想第一次使用matcher.group(0)或matcher.group()作为简写。