正则表达式来解析类似jQuery-selector的字符串

时间:2010-03-01 18:21:28

标签: javascript regex

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'

一种解决方案是将字符串拆分为 #container a 并休息。然后休息并执行recursive exec以获取item()内的项目。

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

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 个答案:

答案 0 :(得分:5)

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

<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

编辑第二部分

正则表达式查找两种类型的字符序列:

  1. 从字符串开头到第一个.开始的一个或多个字符,正则表达式:^[^.]*
  2. 或匹配以.开头的字符序列,后跟除.)\.[^.)]*以外的零个或多个字符,但必须在其前面加)(?=\))。最后一项要求导致.filter 匹配。

答案 1 :(得分:3)

我想你必须迭代。

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之一: - )

答案 2 :(得分:0)

您需要重复多次匹配,从最后一场比赛结束开始(请参阅https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/exec上的while示例):

  

如果正则表达式使用“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

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

答案 3 :(得分:0)

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]);

答案 4 :(得分:0)

带有正则表达式的

text.split()可以解决问题。

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);