Regex to split string on dots that are not inside brackets

Viewed 504

As the title says, I want to write a regex r such that Splitter.onPattern(r).splitToList("a.b.c.d[e.f.g]"); results in

[a, b, c, d[e.f.g]]

I have been playing around trying to get it right, but can't figure it out. I thought "\\.((?!\\[)*)\\]*" should have worked (to match any dot that is followed by a string not containing '[' that ends with ']'), but it still splits on all dots for some reason.

3 Answers

With your shown samples please try following, also assuming that [ and ] are balanced and not nested.

\.(?![^[]*])

Here is the Online demo of regex

Explanation: Match a dot not followed by 0 or more characters without a [ and followed by ].

The trick is to assert that the next bracket char, if there is one, is not a closing bracket.

In regex speak, this is expressed as "is not followed by any number of non-brackets then a ]":

"\\.(?![^\\[\\]]*])"

See live demo.


Note: This does not work for nested dotted expressions like a.b[c.d[e.f].g].h.

Extract them with

[^\[\].]+(?:\[[^\[\]]*])?

See proof.

EXPLANATION

--------------------------------------------------------------------------------
  [^\[\].]+                any character except: '\[', '\]', '.' (1
                           or more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    \[                       '['
--------------------------------------------------------------------------------
    [^\[\]]*                 any character except: '\[', '\]' (0 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    ]                        ']'
--------------------------------------------------------------------------------
  )?                       end of grouping

Java example code:

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

public class Main {
    public static void main(String[] args) {
        final String regex = "[^\\[\\].]+(?:\\[[^\\[\\]]*])?";
        final String string = "a.b.c.d[e.f.g]";
        
        final Pattern pattern = Pattern.compile(regex);
        final Matcher matcher = pattern.matcher(string);

        while (matcher.find()) {
            System.out.println(matcher.group(0));
        }
    }
}
Related