【问题标题】:Splitting a complex string with Regular Expressions使用正则表达式拆分复杂字符串
【发布时间】:2009-05-26 14:06:00
【问题描述】:

我如何使用正则表达式分割这个字符串

string = "a[a=d b&c[e[100&2=34]]] e[cheese=blue and white] x[a=a b]"

进入这个数组

string.split( regexp ) =>

[ "a[a=d b&c[e[100&2=34]]]", "e[cheese=blue and white]", "x[a=a b]" ]

基本规则是 string 应该在 whitespace ( \s ) 处分割,除非 whitespace 存在于 brackets( [ ]);

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    你不能;正则表达式基于没有“堆栈”的状态机,因此您可以记住嵌套级别的数量。

    但也许您可以使用一个技巧:尝试将字符串转换为有效的JSON string。然后你可以使用eval() 将其解析成一个JavaScript 对象。

    【讨论】:

      【解决方案2】:

      如果规则这么简单,我建议只手动执行。逐步检查每个字符,并通过为每个 [ 增加 1 并为每个 ] 减少 1 来跟踪您的嵌套级别。如果到达嵌套 == 0 的空间,则拆分。

      编辑: 我在想我可能还会提到一些语言中的其他模式匹配工具,它们本身就支持这种事情。例如,在 Lua 中,您可以使用 '%b[]' 来匹配平衡的嵌套 []。 (当然,Lua 没有内置的 split 函数……)

      【讨论】:

      • 在使用 Oniguruma 时可以使用正则表达式来执行此操作,因为它具有允许某些类型嵌套的扩展。但是,我不相信任何 javascript impl 包含此扩展,无论如何,我同意 Dolphin 的观点,即非正则表达式方法将更快、更清晰。你可以很容易地为此实现一个状态机。
      【解决方案3】:

      你能分开“(?

      【讨论】:

        【解决方案4】:

        另一种是循环方法,您可以一次解构嵌套的括号,否则很难(TM)确保您的单个正则表达式按预期工作。

        这是一个 ruby​​ 示例:

        str = "a[a=d b&c[e[100&2=34]]] e[cheese=blue and white] x[a=a b]"
        left = str.dup
        tokn=0
        toks=[]
        # Deconstruct
        loop do
          left.sub!(/\[[^\]\[]*\]/,"\{#{tokn}\}")
          break if $~.nil?
          toks[tokn]=$&
          tokn+=1
        end
        left=left.split(/\s+/)
        # Reconstruct
        (toks.size-1).downto(0) do |tokn|
          left.each { |str| str.sub!("\{#{tokn}\}", toks[tokn]) }
        end
        

        上面使用 {n} ,其中 n 在解构过程中是一个整数,因此在某些情况下,字符串中这样的原始输入会破坏重构。不过,这应该说明这种方法。

        但编写通过遍历字符进行拆分的代码更简单、更安全。

        Ruby 中的示例:

        str = "a[a=d b&c[e[100&2=34]]] e[cheese=blue and white] x[a=a b]"
        toks=[]
        level=st=en=0; 
        str.each_byte do |c|
          en+=1; 
          level+=1 if c=='['[0]; 
          level-=1 if c==']'[0]; 
          if level==0 && c==' '[0]
            toks.push(str[st,en-1-st]);
            st=en
          end
        end    
        toks.push(str[st,en-st]) if st!=en 
        p toks
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-23
          • 2017-02-23
          相关资源
          最近更新 更多