How to split a string into two considering end of the string with numbers (which is inside the squre brackets)

Viewed 55

I need to split strings into two with a given separator using regex. Sample Strings and expected output as below

testnames[3] ===> testnames,3
3alpha[0] ====> 3alpha, 0
beta[4]value[2] ===> beta[4]value, 2
gama4[23] ===> gama4, 23
tama[2334] ====> tama, 2334
tes[t[ ===> No matches
try[]t ===> No matches

Each and every String should be split into two if it has numbers within the square bracket at the end of the input string.

Can anyone tell me a regex to do this?

Note: I find out the regex : "\[(-?\d+)\]$". But this only gave me numbers inside the square bracket and not gives the rest of the string

3 Answers

You may use this greedy match replacement with 2 capture groups:

RegEx:

^(.*)\[(\d+)\]

Replacement:

$1, $2

RegEx Demo

Java Code:

String repl = str.replaceFirst("^(.*)\\[(\\d+)\\]", "$1, $2");

RegEx Explained:

  • ^: Start
  • (.*): Greedily match 0 or more of any characters in capture group #1
  • \[: Match a [
  • (\d+): Match 1 or more of digits in capture group #2
  • \]: Match a ]

Stream version:

import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream.of(
                    "testnames[3]",
                    "3alpha[0]",
                    "beta[4]value[2]",
                    "gama4[23]",
                    "tama[2334]",
                    "tes[t[",
                    "try[]t"
                ).forEach(s -> System.out.println(s + " => " + getTokens(s)));  
    }
    static List<String> getTokens(String str){
        return Pattern.compile("(\\w+(?:\\[\\d+\\]\\w+)?)(?=\\[\\d+\\])|(?<=\\[)\\d+(?=\\])")
                        .matcher(str)
                        .results()
                        .map(MatchResult::group)
                        .collect(Collectors.toList());
    }
}

Output:

testnames[3] => [testnames, 3]
3alpha[0] => [3alpha, 0]
beta[4]value[2] => [beta[4]value, 2]
gama4[23] => [gama4, 23]
tama[2334] => [tama, 2334]
tes[t[ => []
try[]t => []

Explanation of the regex at regex101:

enter image description here

Non-Stream version:

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String [] arr = {
                    "testnames[3]",
                    "3alpha[0]",
                    "beta[4]value[2]",
                    "gama4[23]",
                    "tama[2334]",
                    "tes[t[",
                    "try[]t"
        };
        
        for(String s: arr) {
            System.out.println(s + " => " + getTokens(s));
        }
    }
    static List<String> getTokens(String str){
        Pattern pattern = Pattern.compile("(\\w+(?:\\[\\d+\\]\\w+)?)(?=\\[\\d+\\])|(?<=\\[)\\d+(?=\\])");
        Matcher matcher = pattern.matcher(str);
        List<String> list = new ArrayList<>();
        while(matcher.find()) {
            list.add(matcher.group());
        }
        return list;
    }
}

Output:

testnames[3] => [testnames, 3]
3alpha[0] => [3alpha, 0]
beta[4]value[2] => [beta[4]value, 2]
gama4[23] => [gama4, 23]
tama[2334] => [tama, 2334]
tes[t[ => []
try[]t => []

You may use a regex replacement:

String input = "beta[4]value[2]";
String output = input.replaceAll("\\[(\\d+)\\](?!.*\\[\\d+\\])", ", $1");
System.out.println(input);
System.out.println(output);

This prints:

beta[4]value[2]
beta[4]value, 2

The regex pattern used here is \[(\d+)\](?!.*\[\d+\]), which says to:

\[(\d+)\]      match a number in square brackets AND capture that number in $1
(?!.*\[\d+\])  then assert that we do NOT find another [num] term
               this ensures that we only replace the last [num] term

We then replace with comma followed by space and the captured number.

Related