用于实现toFindResult()的正则表达式Java Matcher类
根据this question,在find
和matches()
之间有很大的区别,但两者都以某种形式提供结果
作为一种实用程序,toMatchResult
函数返回matches()
操作的当前结果。我希望我在(1)
下的假设是正确的。(正则表达式为here)
String line = "aabaaabaaabaaaaaab";
String regex = "(a*b)a{3}";
Matcher matcher = Pattern.compile(regex).matcher(line);
matcher.find();
// matcher.matches();(1) --> returns false because the regex doesn't match the whole string
String expectingAab = matcher.group(1);
System.out.println("actually: " + expectingAab);
不幸的是,以下情况不起作用(例外:未找到匹配项):
String line = "aabaaabaaabaaaaaab";
String regex = "(a*b)a{3}";
String expectingAab = Pattern.compile(regex).matcher(line).toMatchResult().group(1);
System.out.println("actually: " + expectingAab);
为什么呢?我的第一个假设是它不起作用,因为正则表达式应该匹配整个字符串;但是同样的异常也会与字符串值aabaaa
一起抛出
当然,matcher需要用find()
设置为正确的状态,但是如果我想使用一个oneliner呢?我实际上为此实现了一个实用程序CALS:
protected static class FindResult{
private final Matcher innerMatcher;
public FindResult(Matcher matcher){
innerMatcher = matcher;
innerMatcher.find();
}
public Matcher toFindResult(){
return innerMatcher;
}
}
public static void main(String[] args){
String line = "aabaaabaaabaaaaaab";
String regex = "(a*b)a{3}";
String expectingAab = new FindResult(Pattern.compile(regex).matcher(line)).toFindResult().group(1);
System.out.println("actually: " + expectingAab);
}
我很清楚,这不是创建oneliner的最佳解决方案,特别是因为它会给垃圾收集器带来沉重的负载
有没有更简单、更好的解决方案
值得注意的是,我正在寻找一个解决方案java8。在Java9之上,匹配逻辑的工作方式不同
# 1 楼答案
toMatchResult()
方法返回上一个匹配操作的状态,无论它是find()
、lookingAt()
还是matches()
你的线路
不调用这些方法中的任何一个,因此,将永远不会有以前的匹配项,并始终生成
IllegalStateException: No match found
如果希望使用一行程序提取第一个匹配的第一组,可以使用
模式需要在实际匹配模式之前
.*?
和之后.*
使用剩余的字符串,并且只保留第一个组作为其内容。需要注意的是,如果不存在匹配项,它将计算为原始字符串因此,如果您想要
matches
而不是find
语义,可以使用它将与示例输入计算为原始字符串,因为它不匹配
如果希望实用程序方法不创建
FindResult
实例,只需使用直接的static
方法即可然而,这是一个典型的过早优化案例。
Pattern.compile
调用创建一个Pattern
对象,加上一组表示模式元素的内部节点对象,matcher
调用创建一个Matcher
实例加上数组来保存组,toMatchResult
调用创建另一个对象实例,当然,group(1)
调用不可避免地会创建一个表示结果的新字符串实例创建
FindResult
实例是此行最便宜的。如果您关心性能,那么如果您多次使用该模式,您将保留Pattern.compile
的结果,因为这是最昂贵的操作,Pattern
实例是不可变和可共享的,正如其文档中明确说明的那样当然,string方法
replaceFirst
和replaceAll
并没有什么神奇的作用,但在幕后执行相同的步骤# 2 楼答案
该方法不需要实例字段即可工作。它可以只是一个静态辅助对象:
用法:
请注意,当
find
找不到任何东西时,您可能希望处理这种情况(感谢使用一行代码,Holger!):