Regex to find if there is only one block of code

前端 未结 4 1499
滥情空心
滥情空心 2021-01-07 12:51

My input is a string, I want to validate that there is only one first-level block of code.

Examples :

{ abc }              TRUE
{ a { bc }         


        
相关标签:
4条回答
  • 2021-01-07 13:19

    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

    0 讨论(0)
  • 2021-01-07 13:23
    (\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*|\(([^()]*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*\))*
    

    Code for brackets

    0 讨论(0)
  • 2021-01-07 13:32

    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,
    0 讨论(0)
  • 2021-01-07 13:38

    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.

    0 讨论(0)
提交回复
热议问题