String replacement when regex reverse group is null in java

Viewed 139

I want to convert a software version number into a github tag name by regular expression.

For example, the version of ognl is usually 3.2.1. What I want is the tag name OGNL_3_2_1

So we can use String::replaceAll(String regex, String replacement) method like this

"3.2.1".replaceAll("(\d+).(\d+).(\d+)", "OGNL_$1_$2_$3")

And we can get the tag name OGNL_3_2_1 easily.

But when it comes to 3.2, I want the regex still working so I change it into (\d+).(\d+)(?:.(\d+))?.

Execute the code again, what I get is OGNL_3_2_ rather than OGNL_3_2. The underline _ at the tail is not what I want. It is resulted by the null group for $3

So how can I write a suitable replacement to solve this case?

When the group for $3 is null, the underline _ should disappear

Thanks for your help !!!

1 Answers

You can make the last . + digits part optional by enclosing it with an optional non-capturing group and use a lambda as a replacement argument with Matcher.replaceAll in the latest Java versions:

String regex = "(\\d+)\\.(\\d+)(?:\\.(\\d+))?";
Pattern p = Pattern.compile(regex);
        
String s="3.2.1";
Matcher m = p.matcher(s);
String result = m.replaceAll(x ->
        x.group(3) != null ? "OGNL_" + x.group(1) + "_" + x.group(2) + "_" + x.group(3) :
              "OGNL_" + x.group(1) + "_" + x.group(2) );
System.out.println(result);

See the Java demo.

The (\d+)\.(\d+)(?:\.(\d+))? pattern (note that literal . are escaped) matches and captures into Group 1 any one or more digits, then matches a dot, then captures one or more digits into Group 2 and then optionally matches a dot and digits (captured into Group 3). If Group 3 is not null, add the _ and Group 3 value, else, omit this part when building the final replacement value.

Related