4

Meaning that I simply want to strip the enclosing braces. I can match "{ this kind of stuff }" with:

"{stuff}".match(/{([^}]*)}/)[1]

Am I asking too much here?

Another example, I've got this javascript code as string:

{
    var foo = {
        bar: 1    
    };

    var foo2 = {
        bar: 2    
    };
}

I want to strip only the outside braces:

var foo = {
    bar: 1
};

var foo2 = {
    bar: 2
}
uɥƃnɐʌuop
  • 14,022
  • 5
  • 58
  • 61
  • 1
    Match opening braces, closing braces, and anything else as three different tokens. Then iterate them to find the closing brace to your opening brace. – Gumbo Mar 30 '13 at 10:32

2 Answers2

9

Try this (I based my code on this answer). It also knows to ignore brackets in strings and comments (single-line and multi-line) - as noted in the comment section of that answer:

var block = /* code block */
    startIndex = /* index of first bracket */,
    currPos = startIndex,
    openBrackets = 0,
    stillSearching = true,
    waitForChar = false;

while (stillSearching && currPos <= block.length) {
  var currChar = block.charAt(currPos);

  if (!waitForChar) {
    switch (currChar) {
      case '{':
        openBrackets++; 
        break;
      case '}':
        openBrackets--;
        break;
      case '"':
      case "'":
        waitForChar = currChar;
        break;
      case '/':
        var nextChar = block.charAt(currPos + 1);
        if (nextChar === '/') {
          waitForChar = '\n';
        } else if (nextChar === '*') {
          waitForChar = '*/';
        }
    }
  } else {
    if (currChar === waitForChar) {
      if (waitForChar === '"' || waitForChar === "'") {
        block.charAt(currPos - 1) !== '\\' && (waitForChar = false);
      } else {
        waitForChar = false;
      }
    } else if (currChar === '*') {
      block.charAt(currPos + 1) === '/' && (waitForChar = false);
    }
  }

  currPos++ 
  if (openBrackets === 0) { stillSearching = false; } 
}

console.log(block.substring(startIndex , currPos)); // contents of the outermost brackets incl. everything inside
Community
  • 1
  • 1
pilau
  • 6,635
  • 4
  • 56
  • 69
1

I agree with Lucero that Regexes are not made for that, but to answer your question:

The problem is that you match everything except }. But since the inside data you want to match contains itself a }, the content of the outer braces is not matched.

{
    var foo = {
        bar: 1
==> };

    var foo2 = {
        bar: 2    
==> };
}

You can use this regex:

{([\S\s]*)}

To explain:

{                   match opening {
    (               group
        [\S\s]      match everything, workaround for the missing s option in JS
              *     greedy, makes it match as much as possible
    )               end group
}                   match closing }
David
  • 3,392
  • 3
  • 36
  • 47
  • Escape the curly braces! `\{([\S\s]*)\}` – MikeM Mar 30 '13 at 12:14
  • Excellent! With that and @MikeM's help, it works beautifully. E.g., this gives me exactly what I was looking for: `"{ Please enter your {field} here: }".match(/\{([\S\s]*)\}/)[1]`. Thanks guys! – uɥƃnɐʌuop Mar 30 '13 at 13:02
  • Escaping the curly braces is not necessary here. JavaScript does not mistake it for a quantity specification because (a) there is no preceding character and (b) the content does not match a quantity specification. Many regular expressions are hard to understand already so I would avoid cluttering them up with unnecessary escape characters. – David Mar 30 '13 at 13:26
  • Fair enough, David, the escaping isn't required here. But (a) is incorrect, and your suggestion that the escaping makes the regex harder to understand is dubious at best. – MikeM Mar 30 '13 at 18:42
  • `{([\S\s]*)}` looks cleaner to me than `\{([\S\s]*)\}`. Also, according to [ECMA 262](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) RegExp syntax definition (page 180-182), a quantifier can only exist after an atom. That and the syntax of a qualifier proves (a) and (b) to be correct. – David Mar 30 '13 at 19:53
  • `/{4}/.test('{4}')` Firefox: Error: invalid quantifier. Chrome: Error: Nothing to repeat. IE: Unexpected quantifier. Clearly it is being interpreted as a quantifier despite having no preceding character. – MikeM Mar 30 '13 at 20:04
  • That surprises me because a term is matched before a quantifier and the only way a quantifier can occur is after an atom. I would really like to see the abstract syntax tree of this regular expression! – David Mar 30 '13 at 21:48
  • Note that in the grammar the definition of _Atom:: PatternCharacter_ is _SourceCharacter_ **but not one of ^ $ \ . * + ? ( ) { } |** Is it therefore ever valid not to escape a curly brace when seeking to match it as a literal? – MikeM Mar 30 '13 at 22:19