Novice
Novice

Reputation: 145

Find the first occurrence with Regex

I would like to be able to find the first occurrence of m² and then numbers in front of it, could be integers or decimal numbers. E.g.

"some text" 38 m² "some text" ,

"some text" 48,8 m² "some text",

"some text" 48 m² "some text", etc..

What I have so far is:

\d\d,\d\s*(\m\u00B2)|\d\d\s*(\m\u00B2)

This right now finds all occurrences, although I guess it could be fixed with findFirst(). Any ideas how to improve the Regex part?

Upvotes: 8

Views: 17922

Answers (4)

Kalju Pärn
Kalju Pärn

Reputation: 21

To find only last one:

    @Test
public void testFindFirstRegExp() {
    String pattern = ".* (\\d+,\\d+) .*";
    Pattern r = Pattern.compile(pattern);
    String line = "some text 44,66 m² some 33,11 m²  text 11,22 m² some text";
    Matcher m = r.matcher(new StringBuilder(line).reverse().toString());
    String expected = "44,66";
    String actual = null;
    if (m.find()) {
        actual = new StringBuilder(m.group(1)).reverse().toString();
    }
    System.out.println("got first:" + actual);
    Assert.assertEquals(expected, actual);

    m = r.matcher(line);
    expected = "11,22";
    actual = null;
    if (m.find()) {
        actual = m.group(1);
    }
    System.out.println("got last:" + actual);
    Assert.assertEquals(expected, actual);
}

prints:

got first:44,66
got last:11,22

Note: think that you need to reverse pattern when needed for ex:

pattern = ".* (\\d+,\\d+-?) .*"; //reverse for (-?\\d+,\\d+)

but this will work as waited:

pattern = " (\\-?\\d+,\\d+) ";

you get all of them in loop:

while (m.find()) {
    actual = m.group(1);
    System.out.println("got last:" + actual);
}

Will print:

got last:44,66
got last:33,11
got last:11,22

Upvotes: 0

anarchy07
anarchy07

Reputation: 11

One simple way of doing it!

description.replaceFirst(@NotNull String regex,
                           @NotNull String replacement)

JAVADoc: Replaces the first substring of this string that matches the given regular expression with the given replacement.

Upvotes: 1

Novice
Novice

Reputation: 145

This is what I came up with you help :) (work in progress, later it should return BigDecimal value), for now it seems to work:

 public static String findArea(String description) {

        String tempString = "";
        Pattern p = Pattern.compile("\\d+(?:,\\d+)?\\s*m\\u00B2");

        Matcher m = p.matcher(description);

        if(m.find()) {
            tempString = m.group();
        }
//remove the m and /u00B2 to parse it to BigDecimal later
        tempString = tempString.replaceAll("[^0-9|,]","");
        System.out.println(tempString);
        return tempString;
    }

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626699

To get the first match, you just need to use Matcher#find() inside an if block:

String rx = "\\d+(?:,\\d+)?\\s*m\\u00B2";
Pattern p = Pattern.compile(rx);
Matcher matcher = p.matcher("E.g. : 4668,68 m² some text, some text 48 m²  etc");
if (matcher.find()){
    System.out.println(matcher.group());
}

See IDEONE demo

Note that you can get rid of the alternation group using an optional non-capturing group (?:..)?

Pattern breakdown:

  • \d+ - 1+ digits
  • (?:,\d+)? - 0+ sequences of a comma followed with 1+ digits
  • \s* - 0+ whitespace symbols
  • m\u00B2 - m2.

Upvotes: 11

Related Questions