代码之家  ›  专栏  ›  技术社区  ›  Neeraj Singh

用于分析类似jquery选择器的字符串的正则表达式

  •  3
  • Neeraj Singh  · 技术社区  · 15 年前
    text = '#container a.filter(.top).filter(.bottom).filter(.middle)';
    
    regex = /(.*?)\.filter\((.*?)\)/;
    
    matches = text.match(regex);
    
    log(matches);
    // matches[1] is '#container a'
    //matchss[2] is '.top'
    

    我想抓住

    matches[1] is '#container a'
    matches[2] is '.top'
    matches[3] is '.bottom'
    matches[4] is '.middle'
    

    一种解决方法是将字符串拆分为 容器A 然后休息。然后使用rest并执行recursive exec以获取内部项()。

    更新: 我正在发布一个有效的解决方案。不过,我正在寻找更好的解决方案。不太喜欢把字符串拆分然后再处理 这是一个可行的解决方案。

    matches = [];
    
    var text = '#container a.filter(.top).filter(.bottom).filter(.middle)';
    var regex = /(.*?)\.filter\((.*?)\)/;
    var match = regex.exec(text);
    firstPart = text.substring(match.index,match[1].length);
    rest = text.substring(matchLength, text.length);
    
    matches.push(firstPart);
    
    regex = /\.filter\((.*?)\)/g;
    while ((match = regex.exec(rest)) != null) {
      matches.push(match[1]);
    }
    log(matches);
    

    寻找更好的解决方案。

    5 回复  |  直到 14 年前
        1
  •  5
  •   Bart Kiers    15 年前

    这将与您发布的单个示例相匹配:

    <html>
      <body>
        <script type="text/javascript">
          text = '#container a.filter(.top).filter(.bottom).filter(.middle)';
          matches = text.match(/^[^.]*|\.[^.)]*(?=\))/g);
          document.write(matches);
        </script>
      </body>
    </html>
    

    产生:

    #container a,.top,.bottom,.middle 
    

    编辑

    这里有一个简短的解释:

    ^         # match the beginning of the input
    [^.]*     # match any character other than '.' and repeat it zero or more times
              #
    |         # OR
              #
    \.        # match the character '.'
    [^.)]*    # match any character other than '.' and ')' and repeat it zero or more times
    (?=       # start positive look ahead
      \)      #   match the character ')'
    )         # end positive look ahead
    

    编辑第二部分

    regex查找两种类型的字符序列:

    1. 一个或多个字符,从字符串开始到第一个 . ,正则表达式: ^[^.]*
    2. 或者它匹配以 后跟零个或多个字符,而不是 ) , \.[^.)]* 但是 必须 有一个 ) 在前面: (?=\)) . 最后一项要求导致 .filter 匹配。
        2
  •  3
  •   Pointy    15 年前

    我想你得反复练习。

    var head, filters = [];
    text.replace(/^([^.]*)(\..*)$/, function(_, h, rem) {
      head = h;
      rem.replace(/\.filter\(([^)]*)\)/g, function(_, f) {
        filters.push(f);
      });
    });
    console.log("head: " + head + " filters: " + filters);
    

    能够将函数用作string.replace的第二个参数是我最喜欢的javascript特性之一:-)

        3
  •  0
  •   Blixt    15 年前

    您需要重复进行几次匹配,从最后一次匹配结束的地方开始(请参见 while https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/exec ):

    如果正则表达式使用“g”标志,则可以多次使用exec方法在同一字符串中查找连续匹配项。执行此操作时,搜索从正则表达式的lastIndex属性指定的str子字符串开始。例如,假设您有以下脚本:

    var myRe = /ab*/g;
    var str = "abbcdefabh";
    var myArray;
    while ((myArray = myRe.exec(str)) != null)
    {
      var msg = "Found " + myArray[0] + ".  ";
      msg += "Next match starts at " + myRe.lastIndex;
      print(msg);
    }
    

    此脚本显示以下文本:

    Found abb. Next match starts at 3
    Found ab. Next match starts at 9
    

    然而 ,使用自定义的解析器会更好地解决此情况。如果你问我,正则表达式不是解决这个问题的有效方法。

        4
  •  0
  •   Darin Dimitrov    15 年前
    var text = '#container a.filter(.top).filter(.bottom).filter(.middle)';
    var result = text.split('.filter');
    
    console.log(result[0]);
    console.log(result[1]);
    console.log(result[2]);
    console.log(result[3]);
    
        5
  •  0
  •   Imran    15 年前

    text.split() 用regex做把戏。

    var text = '#container a.filter(.top).filter(.bottom).filter(.middle)';
    var parts = text.split(/(\.[^.()]+)/);
    var matches = [parts[0]];
    
    for (var i = 3; i < parts.length; i += 4) {
        matches.push(parts[i]);
    }
    
    console.log(matches);