DavidL
DavidL

Reputation: 915

regex to match outermost pattern

I'd like to know the regex that matches everything inside {}. The string might contain nested {}; I don't care about them.

Example string: {Don't} trust me. I'm a {very very {evil}} good guy.

I want the result to be Don't and very very {evil}.

The only regex I have at the moment is /{\w+}/ which only captures evil. It returns Dont also if it doesn't have the apostrophe.

Upvotes: 1

Views: 901

Answers (2)

Rain Diao
Rain Diao

Reputation: 926

@Rohit is correct.

if you use js or java, and do not the the deepth of the nested brackets, you have to write your own parser.

but if you use C# or perl, you can use "balancing group" to achieve this, which is a advanced regex feature, and not supported by js. :(

Upvotes: 0

Rohit Jain
Rohit Jain

Reputation: 213213

Since you are having nested braces, so the regex to extract the parts between the braces is not as straight as: - \{.+?\}. This regex will stop at the first } it finds. So, it will not behave nicely for nested braces. For that, you need a slightly more complex regex. However, I would suggest not to use Regex for such kind of problems. Regex is not good enough to consider matching pairs of brackets. They can only parse regular language. For anything higher than that, you should write your own parser.

That being said, you can try this regex: -

"/\{((?:[^{}]*\{[^{}]*\})*[^{}]*?)\}/"

And get the group 1. This will consider your nested braces, provided they are balanced. And you don't have your braces as a part of actual string.


Apart from the above solution, you can have a look at this sample parser, which would work for your particular case. In fact this should work for any form of nested braces, provided you have balanced braces: -

String str = "{Don't} trust me. I'm a {very very {evil}} good guy.";

List<String> words = new ArrayList<>();
int openCount = 0;

StringBuilder builder = new StringBuilder();

for (int i = 0; i < str.length(); i++) {
    char ch = str.charAt(i);

    if (ch == '{') {
        if (openCount == 1) {
            builder.append(ch);
        }
        openCount += 1;

    } else if (ch == '}') {

        if (openCount > 1) {
            openCount--;
            builder.append(ch);

        } else {
            words.add(builder.toString());
            openCount--;
            builder = new StringBuilder();
        }

    } else {
        if (openCount >= 1) {
            builder.append(ch);
        }
    }
}

System.out.println(words);

Output: -

[Don't, very very {evil}]

Upvotes: 5

Related Questions