java - 为什么我的正则表达式在 RegexPlanet 和 regex101 上有效,但在我的代码中却无效?

标签 java regex

给定字符串 #100=SAMPLE('Test','Test', 我想提取 100Test。我创建了正则表达式 ^#(\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 允许您多次查询它,以便您可以找到表达式、获取组、再次查找表达式、获取组等。

这意味着它会在每次调用后保持状态 - 包括成功匹配的组以及继续搜索的位置。

当你连续运行两个匹配/查找方法时,你得到的是:

  1. matches() - 在字符串的开头匹配,设置组。
  2. find() - 尝试在先前匹配/找到的事件之后找到模式的下一次出现,设置组。

当然,在您的情况下,文本不包含 两次 模式出现,只有一次。因此,虽然 matches() 成功并设置了正确的组,但 find() 无法找到另一个匹配项,并且组无效(组在匹配/查找失败)。

这就是您收到错误消息的原因。

现在,如果您只是想看看 matchesfind 之间的区别,那么将它们都放在程序。但是你需要在它们之间使用 reset(),这将导致 find() 不会尝试从 matches() 停止的地方继续(如果 matches() 成功,它总是会失败)。相反,它将从头开始扫描,就像您有一个新的 Matcher 一样。它会成功并为您提供群组。

但正如此处其他答案所暗示的那样,如果您不只是想比较 matchesfind 的结果,而只是想匹配您的模式并获得结果,那么你应该只选择其中的一个

  • matches() 将尝试匹配整个字符串。出于这个原因,如果它成功了,在它之后运行 find() 永远不会成功 - 因为它从字符串的末尾开始搜索。如果您使用 matches(),则您不需要在模式的开头和结尾使用 ^$ 等 anchor 。<
  • find() 将尝试匹配字符串中的任何位置。它将从左侧开始扫描,但不要求实际匹配从那里开始。也可以多次使用。
  • lookingAt() 将尝试匹配字符串的开头,但不一定匹配完整的字符串。这就像在您的模式开头有一个 ^ anchor 。

所以你选择其中一个适合你的,然后使用它,然后你就可以使用这些组了。在尝试使用组之前,请始终测试匹配是否成功!

关于java - 为什么我的正则表达式在 RegexPlanet 和 regex101 上有效,但在我的代码中却无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32433104/

相关文章:

java - 从 java bean 准备查询字符串

用于 Mark Nelson 实现 Ukkonen 算法的后缀树中首次出现模式 s 的 java 模式匹配

java - 自定义注解过滤器 Spring boot

java - 如何使用Apache POI实现Excel的数组公式功能

java - 解析SQL Developer时间戳格式DD-MON-RRRR HH24 :MI:SSXFF to Java Timestamp

java - 如何通过 Apache POI 更改 Excel 旭日图中点的图形属性

sql-server - 用 TSQL 替换字符串中的每个第二个字符实例

java - 将文档分为段落

PHP RegEx - 获取所有数字

regex - 在 Notepad++ 中,使用正则表达式替换除与给定表达式匹配的行之外的所有行