3

I'm executing this regex code expecting a grouping value of 11, but am getting a 1. Seems like the grouping contains the correct regex for getting one or more digits prior to a known value. I'm sure it is simple, bit I cannot seem to figure it out.

String mydata = "P0Y0M0W0DT11H0M0S";
Pattern pattern = Pattern.compile("P.*(\\\\d+)H.*");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find()){
    System.out.println(matcher.group(1));
}
Tunaki
  • 132,869
  • 46
  • 340
  • 423
jim stone
  • 61
  • 3

2 Answers2

2

Try this

public static void main(String a1[]) {
        String mydata = "P0Y0M0W0DT11H0M0S";
        Pattern pattern = Pattern.compile("P.*?(\\d+)H.*");
        Matcher matcher = pattern.matcher(mydata);
        if (matcher.find()){
            System.out.println(matcher.group(1));
        }

    }

Output

11
RockAndRoll
  • 2,247
  • 2
  • 16
  • 35
2

The problem is that .* will try to consume/match as much as possible before the next part is checked. Thus in your regex P.*(\d+)H.* the first .* will match 0Y0M0W0DT1 since that's as much as can be matched with the group still being able to match a single digit afterwards.

If you make that quantifier lazy/reluctant (i.e. .*?), it will try to match as little as possible so of the possible matches 0Y0M0W0DT1 and 0Y0M0W0DT it will select the shorter one and leave all the digits for the group to match.

Thus the regex P.*?(\d+)H.* should do what you want.

Additional note: since you're using Matcher#find() you'd not need the catch-all-expression .* at the end. It would also match any string that contains the character H preceeded by at least one digit and a P somewhere in front of those digits. So if you want to be more restrictive your regex would need to be enhanced.

Thomas
  • 87,414
  • 12
  • 119
  • 157