代码之家  ›  专栏  ›  技术社区  ›  Floyd user1988754

如何将字符串拆分为“,”或“[]”,除非“,”位于“”中

  •  3
  • Floyd user1988754  · 技术社区  · 14 年前

    我搜索一个regex来拆分以下字符串:

    aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]
    aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]
    aaa[bbb, ccc[ddd, ddd],nnn[0,3]]
    aaa[bbb,ddd[0,3]]
    

    “[”或“]”或“,”,除非“,”位于“”中。例如:将'aaa[bbb,ccc[ddd'拆分为aaa,bbb,ccc,ddd是允许的,但不允许eee:1,mmm:999。

    结果是:

    aaa, bbb, ccc, ddd, {eee:1,mmm:999}, nnn, 0, 3
    aaa, bbb, ccc, ddd, {eee:1, mmm:[123,555]}], nnn, 0, 3
    aaa, bbb, ccc, ddd, ddd, nnn, 0, 3
    aaa, bbb, ddd, 0, 3
    

    我读过一些其他的问题,但是我不能修改regex的文章来做我想做的。

    表达式的目标语言是javascript。

    5 回复  |  直到 14 年前
        1
  •  1
  •   Qtax    14 年前

    Perl/PCRE regex也应该在JS中工作(只要不嵌套):

    $_ = 'aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]
    aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]
    aaa[bbb, ccc[ddd, ddd],nnn[0,3]]
    aaa[bbb,ddd[0,3]]';
    
    @r = /[^][,{}]+|\{[^}]*}/g;
    print join ", ", @r;
    

    输出:

    aaa, bbb, ccc, ddd, {eee:1,mmm:999}, nnn, 0, 3,
    aaa, bbb, ccc, ddd, {eee:1, mmm:[123,555]}, nnn, 0, 3,
    aaa, bbb,  ccc, ddd,  ddd, nnn, 0, 3,
    aaa, bbb, ddd, 0, 3
    

    粗略翻译成javascript:

    var input =
        "aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]\n" +
        "aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]\n" +
        "aaa[bbb, ccc[ddd, ddd],nnn[0,3]]\n" +
        "aaa[bbb,ddd[0,3]]";
    
    var re = /[^][,{}]+|\{[^}]*}/g;
    
    var result = [];
    while (!!(match = re.exec(input)))
    {
        result.push(match[0]);
    }
    
    // Using <<value>> rather than just a comma, for clarity around
    // whether and how "{...}" was processed or not.
    write("<<" + result.join(">><<") + ">>");
    

    不清楚问题的输入或结果数据中的换行符是什么。在上面,它们是输入数据中的换行符,然后在结果中不进行特殊处理。如果需要特殊处理,可以适当编辑操作。因此,这是上述结果(同样,使用 << >> 作为分隔符而不是 , 为了明确是否 {...} 得到处理):

    <<aaa>><<bbb>><<ccc>><<ddd>><<{eee:1,mmm:999}>><<nnn>><<0>><<3>><<
    aaa>><<bbb>><<ccc>><<ddd>><<{eee:1, mmm:[123,555]}>><<nnn>><<0>><<3>><<
    aaa>><<bbb>><< ccc>><<ddd>><< ddd>><<nnn>><<0>><<3>><<
    aaa>><<bbb>><<ddd>><<0>><<3>>
    
        2
  •  2
  •   SLaks    14 年前

    使用正则表达式和处理无限嵌套大括号是不可能做到这一点的;您需要一个基于堆栈的解析器。

        3
  •  1
  •   Tim Goodman    14 年前

    一种非regex方法是编写一个循环,逐个字符检查字符串。当它遇到 { ,增加一个变量。当它遇到 } ,取消变量增量。当它遇到 , 您递增/递减的变量是零,加上 , 到一个列表。完成后,您将得到要拆分字符串的位置列表。

    我假设没有任何右括号 } 在打开大括号之前 { 否则,您可能希望忽略放错的右大括号,而不是将变量反增量为负数。

        4
  •  0
  •   kennebec    14 年前

    把剩下的分开-

    function customRx(s){
     s= s.replace(/[\[\],\s]+$/g,'');
     var Rx=/,?(\{[^}]+\}),?/g, Rs=/[\[\],\s]+/, Rc=/^,|,$/g;
     var A= [], i= 0, M, z= 0;
     while((M= Rx.exec(s))!= null){
      i= M.index;
      if(i> z){
       A.push(s.substring(z, i).split(Rs));
      }
      z= Rx.lastIndex;
      A.push(s.substring(i, z).replace(Rc,''));
     }
     if(s.length> z){
      A.push(s.substring(z).split(Rs));
     }
     return A;
    }
    

    //测试

    var s1= 'aaa[bbb,ccc[ddd,{eee:1,mmm:999}],nnn[0,3]]'+
    'aaa[bbb,ccc[ddd,{eee:1, mmm:[123,555]}],nnn[0,3]]'+
    'aaa[bbb, ccc[ddd, ddd],nnn[0,3]]'+
    'aaa[bbb,ddd[0,3]]';
    

    警报(customrx(s1).join(',');

    返回值(添加新行)>

    AAA,BBB,CCC,DDD,EEE:1,MMM:999,

    nnn,0,3,aaa,bbb,ccc,ddd,eee:1,mmm:[123555],

    nnn,0,3,aaa,bbb,ccc,ddd,ddd,nnn,

    0,3,AAA,BBB,DDD,0,3

        5
  •  0
  •   Alan Moore Chris Ballance    14 年前

    假设您正在逐行处理文本,并且大括号不能嵌套,则此拆分regex应该可以工作:

    / *[\[\],]+ *(?=[^{}]*(?:\{[^{}]*\}[^{}]*)*$)/
    

    第一部分-- *[\[\],]+ * --匹配一个或多个 [ , ] , 以及周围的空间。其余的是一个前瞻性声明,如果匹配字符前面有大括号,它们将以平衡对的形式出现。如果文本格式正确,则确保不会在大括号内发生匹配。