Pattern/Matcher group() 在 Java 中获取子字符串?

Posted

技术标签:

【中文标题】Pattern/Matcher group() 在 Java 中获取子字符串?【英文标题】:Pattern/Matcher group() to obtain substring in Java? 【发布时间】:2012-11-25 21:36:32 【问题描述】:

更新:感谢所有精彩的回复!我尝试了许多不同的正则表达式模式,但不明白为什么 m.matches() 没有做我认为应该做的事情。当我改用 m.find() 并调整正则表达式模式时,我能够到达某个地方。


我想匹配 Java 字符串中的模式,然后使用正则表达式(如 Perl 的 $& 运算符)提取匹配的部分。

这是我的源字符串“s”:DTSTART;TZID=America/Mexico_City:20121125T153000 我想提取“America/Mexico_City”部分。

我认为我可以使用 Pattern 和 Matcher,然后使用 m.group() 进行提取,但它没有按我预期的那样工作。我尝试过使用不同的正则表达式字符串,唯一似乎在 m.matches() 上命中的是".*TZID.*",这是毫无意义的,因为它只返回整个字符串。有人可以启发我吗?

 Pattern p = Pattern.compile ("TZID*:"); // <- change to "TZID=([^:]*):"
 Matcher m = p.matcher (s);
 if (m.matches ()) // <- change to m.find()
    Log.d (TAG, "looking at " + m.group ()); // <- change to m.group(1)

【问题讨论】:

看起来像 ics (iCal) 文件中的一行 - 为什么不使用 ical4j.sourceforge.net 或等效项? 确实如此。我从 ical4j 开始,但在解析 ics 文件时出现错误,因此放弃了它。如果我需要更多功能而不仅仅是提取 DTSTART 行,我可能会再试一次。 【参考方案1】:

星号前少了一个点。您的表达式将匹配任意数量的大写 Ds。

Pattern p = Pattern.compile ("TZID[^:]*:");

您还应该添加一个捕获组,除非您想捕获所有内容,包括"TZID"":"

Pattern p = Pattern.compile ("TZID=([^:]*):");

最后,您应该使用正确的 API 来搜索字符串,而不是尝试匹配整个字符串。

Pattern p = Pattern.compile("TZID=([^:]*):");
Matcher m = p.matcher("DTSTART;TZID=America/Mexico_City:20121125T153000");
if (m.find()) 
    System.out.println(m.group(1));

这个prints

America/Mexico_City

【讨论】:

【参考方案2】:

你使用了错误的模式,试试这个:

Pattern p = Pattern.compile(".*?TZID=([^:]+):.*");
Matcher m = p.matcher (s);
if (m.matches ())
    Log.d (TAG, "looking at " + m.group(1));

.*? 将匹配一开始直到TZID= 的任何内容,然后TZID= 将匹配,一个组将开始并匹配所有直到:,该组将在此处关闭,然后: 将匹配.* 将匹配字符串的其余部分,现在您可以在 group(1) 中获得所需的内容

【讨论】:

我删除了我几乎相同的答案以支持你的答案。你有一个更好的正则表达式。【参考方案3】:

这应该很好用:

Pattern p = Pattern.compile("TZID=(.*?):");
Matcher m = p.matcher(s);
if (m.find()) 
    String zone = m.group(1); // group count is 1-based
    . . .

另一种正则表达式是"TZID=([^:]*)"。我不确定哪个更快。

【讨论】:

【参考方案4】:

为什么不简单地使用 split as:

  String origStr = "DTSTART;TZID=America/Mexico_City:20121125T153000";
  String str = origStr.split(":")[0].split("=")[1];

【讨论】:

非常优雅的解决方案。谢谢【参考方案5】:

您使用m.match() 尝试匹配整个字符串,如果您将使用m.find(),它将在内部搜索匹配项,我还改进了您的正则表达式以使用零宽度查找排除 TZID 前缀:

     Pattern p = Pattern.compile("(?<=TZID=)[^:]+"); //
     Matcher m = p.matcher ("DTSTART;TZID=America/Mexico_City:20121125T153000");
     if (m.find()) 
         System.out.println(m.group());
     

【讨论】:

以上是关于Pattern/Matcher group() 在 Java 中获取子字符串?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA正则表达式,matcher.find和 matcher.matches的区别

Java 正则提取银行短信内容

java Pattern和Matcher详解

正则表达式如何获取匹配的部分

韩顺平循序渐进学Java零基础 第27章 正则表达式

正则表达式相关