Java 解析文本体以匹配两个正则表达式的最有效方法是什么?

Java 解析文本体以匹配两个正则表达式的最有效方法是什么?,java,regex,Java,Regex,我是Java新手,想了解我在做什么。有没有更有效的方法来编程?我在connectionInfo中有一个文本主体,我将其分成几行,以便为匹配程序进行解析。我是否可以从connectionInfo中检索匹配的文本,而不将其分成几行?这是匹配两个字符串的有效方法吗?我是否需要为此创建两个单独的Matcher对象 // Parse rid and rtoe (estimated time to completion) String rid = null; String rtoe = null; Patt

我是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");

你正在找到一个好的解决方案,但有些小事情你可以调整,使之更好

如果无法找到模式,则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");
我们也可能只使用一个模式对象,但我喜欢您最初使用它的方式。这只是因为它更容易读取,然后一对字符串引用被提供给一个模式。希望这有帮助

最后一个注意事项:您是否正在使用matcher.group(1)?这将为您提供第二个分组,而不是第一个分组。如果需要第一个,请使用matcher.group(0)或matcher.group()作为缩写

我是否可以从
connectionInfo
检索匹配的文本 把它分成几行

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

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

跳过行分割和迭代,只需对每个模式进行一次匹配,效率会更高。检测一个或两个不匹配的错误条件也会更方便:

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对象

// 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");
一个
匹配器
特定于一个特定的
模式
,因此对于您所给的
模式
s,是的,您需要两个
匹配器
s。这可能不需要担心,但如果所显示的代码运行如此频繁,以致于产生的性能或垃圾量是一个真正的问题,那么有一些方法可以缓解它:

  • 对整个类只编译一次每个
    模式
    ,并将其记录在静态字段中。模式编译相对来说比较昂贵,所以如果您的代码是一个瓶颈,那么这可能是一个重大的胜利

  • 如果且仅当该方法不受并发调用的保护时,为每个模式创建一个单独的
    匹配器
    ,同样记录在静态字段中,并在需要时通过其一个arg
    reset()
    方法将其绑定到每个新输入。这将减少产生的垃圾量,但只有当这种方法对GC的巨大问题做出重大贡献时,它才值得


好的,您可以运行正则表达式而不拆分它们,并使用一段时间(ridMatcher.find()| | rtoMatcher.find())。这样,您只需迭代实际匹配项。您只需要确保您的正则表达式足够健壮,这样做就不会在分组中获得额外的字符。
RID=
RTOE=
是否在一行的开头?文件有多大?是的,在四个空格之后,@casimimirithippolyte,并且文件不是大的。您也不能分割您的文件,使用单个锚定模式:
(?m)^{4}(R(?:ID | TOE))=(.*)
,这样您只需使用
find
解析整个文件一次,并且您只需测试捕获组1以确定它是RID还是RTOE。(您还可以使用两个捕获组更快地了解它:
(?m)^{4}R(?(ID)|(TOE))=(.*)
,当组2为空时,它是RID)不需要两个
匹配器与不需要两个变量之间存在差异。您的代码使用了两个
匹配器
,如果有两个不同的模式需要匹配,这确实是必要的。@JohnBollinger-John是正确的。我把她的问题解释为“我需要两个变量吗?”,这是不正确的。谢谢!这正是我需要知道的。