Pattern/Matcher group() to obtain substring in Jav

2019-01-26 06:56发布

UPDATE: Thanks for all the great responses! I tried many different regex patterns but didn't understand why m.matches() was not doing what I think it should be doing. When I switched to m.find() instead, as well as adjusting the regex pattern, I was able to get somewhere.


I'd like to match a pattern in a Java string and then extract the portion matched using a regex (like Perl's $& operator).

This is my source string "s": DTSTART;TZID=America/Mexico_City:20121125T153000 I want to extract the portion "America/Mexico_City".

I thought I could use Pattern and Matcher and then extract using m.group() but it's not working as I expected. I've tried monkeying with different regex strings and the only thing that seems to hit on m.matches() is ".*TZID.*" which is pointless as it just returns the whole string. Could someone enlighten me?

 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)

5条回答
神经病院院长
2楼-- · 2019-01-26 07:31

You are missing a dot before the asterisk. Your expression will match any number of uppercase Ds.

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

You should also add a capturing group unless you want to capture everything, including the "TZID" and the ":"

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

Finally, you should use the right API to search the string, rather than attempting to match the string in its entirety.

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

This prints

America/Mexico_City
查看更多
ゆ 、 Hurt°
3楼-- · 2019-01-26 07:33

This should work nicely:

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

An alternative regex is "TZID=([^:]*)". I'm not sure which is faster.

查看更多
老娘就宠你
4楼-- · 2019-01-26 07:35

You are using the wrong pattern, try this:

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

.*? will match anything in the beginning up to TZID=, then TZID= will match and a group will begin and match everything up to :, the group will close here and then : will match and .* will match the rest of the String, now you can get what you need in group(1)

查看更多
看我几分像从前
5楼-- · 2019-01-26 07:45

Why not simply use split as:

  String origStr = "DTSTART;TZID=America/Mexico_City:20121125T153000";
  String str = origStr.split(":")[0].split("=")[1];
查看更多
男人必须洒脱
6楼-- · 2019-01-26 07:51

You use m.match() that tries to match the whole string, if you will use m.find(), it will search for the match inside, also I improved a bit your regexp to exclude TZID prefix using zero-width look behind:

     Pattern p = Pattern.compile("(?<=TZID=)[^:]+"); //
     Matcher m = p.matcher ("DTSTART;TZID=America/Mexico_City:20121125T153000");
     if (m.find()) {
         System.out.println(m.group());
     }
查看更多
登录 后发表回答