Skip to content Skip to sidebar Skip to footer

Regex To Find If There Is Only One Block Of Code

My input is a string, I want to validate that there is only one first-level block of code. Examples : { abc } TRUE { a { bc } } TRUE { a {{}} } TRU

Solution 1:

EDIT: I started writing the answer before JavaScript was specified. Will leave it as for the record as it fully explains the regex.

In short: In JavaScript I cannot think of a reliable solution. In other engines there are several options:

  • Recursion (on which I will expand below)
  • Balancing group (.NET)

For solutions 2 (which anyhow won't work in JS either), I'll refer you to the example in this question

Recursive Regex

In Perl, PCRE (e.g. Notepad++, PHP, R) and the Matthew Barnett's regex module for Python, you can use:

^({(?:[^{}]++|(?1))*})$

The idea is to match exactly one set of nested braces. Anything more makes the regex fail.

See what matches and fails in the Regex Demo.

Explanation

  • The ^ anchor asserts that we are at the beginning of the string
  • The outer parentheses define Group 1 (or Subroutine 1)
  • { match the opening brace
  • (?: ... )* zero or more times, we will...
  • [^{}]++ match any chars that are not { or }
  • OR |
  • (?1) repeat the expression of subroutine 1
  • } match closing brace
  • The $ anchor asserts that we are at the end of the string. Therefore,

Solution 2:

This is a terrible workaround.

Since this is in Javascript there's not really much to do, but please see the following regex:

/^{([^{}]*|{})*}$/

Where you copy ([^{}]*|{})* and insert it between the last pair of curly brackets (rinse and repeat). Every duplication of this pattern allows another level of nesting between your elements. (This is a workaround for the lack of recursion in JS regex, required to solve nesting problems.)

Online Regex Demo


Solution 3:

In JavaScript what you need to do is strip out all the nested blocks until no nested blocks are left and then check whether there are still multiple blocks:

var r = input.replace(/(['"])(?:(?!\1|\\).|\\.)*\1|\/(?![*/])(?:[^\\/]|\\.)+\/[igm]*|\/\/[^\n]*(?:\n|$)|\/\*(?:[^*]|\*(?!\/))*\*\//gi, '');

if (r.split('{').length != r.split('}').length || r.indexOf('}') < r.indexOf('{')) {
    // ERROR
    continue;
}

while (r.match(/\{[^}]*\{[^{}]*\}/))
    r = r.replace(/(\{[^}]*)\{[^{}]*\}/g, '$1');
if (r.match(/\}.*\{/)
    // FALSE
else
    // TRUE

Working JSFiddle

Be sure to make the regex in the while and the regex in the replace match the same otherwise this might result in infinite loops.

Updated to address ERROR cases and remove anything in comments, strings and regex-literals first after Unihedron asked.


Solution 4:

(\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*

Code for brackets


Post a Comment for "Regex To Find If There Is Only One Block Of Code"