skip to Main Content

I’m working on a regex pattern to match nested parentheses with exponential depth. While I have a working solution for shallow nesting, it fails when the nesting depth becomes very deep.

Here’s my current regex pattern:

const regex = /(([^()]+))/;
const text = "(((A))) (((((B))))) (((((((C)))))))";

const matches = text.match(regex);
console.log(matches);

In this example, I want to match the innermost content within the deepest set of parentheses, like "C". However, my current regex code only matches "A" and "B."

I’m looking for a regex pattern that can handle matching the innermost content within deeply nested parentheses like the "C" in the example. Any insights or corrections to my regex code would be greatly appreciated!

2

Answers


  1. You forgot the global modifier, /g

    const regex = /(([^()]+))/g;
    const text = "(((A))) (((((B))))) (((((((C)))))))";
    
    const matches = text.match(regex);
    console.log(matches);

    You can avoid parenthesis in your capture result and the need for capture groups with a few lookarounds:

    const regex = /(?<=()[^()]+(?=))/g;
    const text = "(((A))) (((((B))))) (((((((C)))))))";
    
    const matches = text.match(regex);
    console.log(matches);

    Depending on the complexity of your input, you could easily run into issues. For example, is the expectation that D, not C, gets matched? Whoops…

    const regex = /(?<=()[^()]+(?=))/g;
    const text = "(((A))) (((((B))))) (((((((C))(((((D))))))))))";
    
    const matches = text.match(regex);
    console.log(matches);
    Login or Signup to reply.
  2. Seems not possible with 1 regexp but you could match opening parentheses + content and check whether the closing parentheses match:

    const text = "(((A))) (((((B))))) (((((((C))))))) ((((bad parentheses))((good ones))";
    
    // captures opening parentheses + content
    const regex = /((+)([^)]+)/g;
    const result = [];
    
    let me;
    while(m = regex.exec(text)){
      // check whether closing parentheses match
      const from = m.index + m[0].length;
      const closing = text.slice(from, from + m[1].length + 1);
      new RegExp('^\){' + m[1].length + '}($|[^)])').test(closing) && result.push(m[2]);
    }
    
    console.log('captures:', ...result.map(JSON.stringify));
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search