给定字符串 #100=SAMPLE('Test','Test',
我想提取 100
和 Test
。我创建了正则表达式 ^#(\d+)=SAMPLE\('([\w-]+)'.*
用于此目的。
我在 RegexPlanet 上测试了正则表达式和 regex101 .这两种工具都给了我预期的结果,但是当我尝试在我的代码中使用它时,我没有得到匹配项。我使用以下代码片段来测试正则表达式:
final String line = "#100=SAMPLE('Test','Test',";
final Pattern pattern = Pattern.compile("^#(\\d+)=SAMPLE\\('([\\w-]+)'.*");
final Matcher matcher = pattern.matcher(line);
System.out.println(matcher.matches());
System.out.println(matcher.find());
System.out.println(matcher.group(1));
System.out.println(matcher.group(2));
输出是
true
false
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 Test.main(Test.java:15)
我使用 Java 8 编译和运行该程序。为什么正则表达式适用于在线工具,但不适用于我的程序?
最佳答案
A Matcher
object 允许您多次查询它,以便您可以找到表达式、获取组、再次查找表达式、获取组等。
这意味着它会在每次调用后保持状态 - 包括成功匹配的组以及继续搜索的位置。
当你连续运行两个匹配/查找方法时,你得到的是:
matches()
- 在字符串的开头匹配,设置组。find()
- 尝试在先前匹配/找到的事件之后找到模式的下一次出现,设置组。
当然,在您的情况下,文本不包含 两次 模式出现,只有一次。因此,虽然 matches()
成功并设置了正确的组,但 find()
无法找到另一个匹配项,并且组无效(组在匹配/查找失败)。
这就是您收到错误消息的原因。
现在,如果您只是想看看 matches
和 find
之间的区别,那么将它们都放在程序。但是你需要在它们之间使用 reset()
,这将导致 find()
不会尝试从 matches()
停止的地方继续(如果 matches()
成功,它总是会失败)。相反,它将从头开始扫描,就像您有一个新的 Matcher
一样。它会成功并为您提供群组。
但正如此处其他答案所暗示的那样,如果您不只是想比较 matches
和 find
的结果,而只是想匹配您的模式并获得结果,那么你应该只选择其中的一个。
matches()
将尝试匹配整个字符串。出于这个原因,如果它成功了,在它之后运行find()
永远不会成功 - 因为它从字符串的末尾开始搜索。如果您使用matches()
,则您不需要在模式的开头和结尾使用^
和$
等 anchor 。<find()
将尝试匹配字符串中的任何位置。它将从左侧开始扫描,但不要求实际匹配从那里开始。也可以多次使用。lookingAt()
将尝试匹配字符串的开头,但不一定匹配完整的字符串。这就像在您的模式开头有一个^
anchor 。
所以你选择其中一个适合你的,然后使用它,然后你就可以使用这些组了。在尝试使用组之前,请始终测试匹配是否成功!
关于java - 为什么我的正则表达式在 RegexPlanet 和 regex101 上有效,但在我的代码中却无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32433104/