最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Regular expression to parse jQuery-selector-like string - Stack Overflow

programmeradmin0浏览0评论
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'

I expect to capture

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

One solution would be to split the string into #container a and rest. Then take rest and execute recursive exec to get item inside ().

Update: I am posting a solution that does work. However I am looking for a better solution. Don't really like the idea of splitting the string and then processing Here is a solution that works.

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

Looking for a better solution.

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'

I expect to capture

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

One solution would be to split the string into #container a and rest. Then take rest and execute recursive exec to get item inside ().

Update: I am posting a solution that does work. However I am looking for a better solution. Don't really like the idea of splitting the string and then processing Here is a solution that works.

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

Looking for a better solution.

Share Improve this question edited Jul 9, 2011 at 6:40 Brad Mace 27.9k18 gold badges109 silver badges152 bronze badges asked Mar 1, 2010 at 18:21 Neeraj SinghNeeraj Singh 2,1464 gold badges19 silver badges24 bronze badges 0
Add a ment  | 

5 Answers 5

Reset to default 5

This will match the single example you posted:

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

which produces:

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

EDIT

Here's a short explanation:

^         # 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

EDIT part II

The regex looks for two types of character sequences:

  1. one ore more characters starting from the start of the string up to the first ., the regex: ^[^.]*
  2. or it matches a character sequence starting with a . followed by zero or more characters other than . and ), \.[^.)]*, but must have a ) ahead of it: (?=\)). This last requirement causes .filter not to match.

You have to iterate, I think.

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

The ability to use functions as the second argument to String.replace is one of my favorite things about Javascript :-)

You need to do several matches repeatedly, starting where the last match ends (see while example at https://developer.mozilla/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/exec):

If your regular expression uses the "g" flag, you can use the exec method multiple times to find successive matches in the same string. When you do so, the search starts at the substring of str specified by the regular expression's lastIndex property. For example, assume you have this script:

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

This script displays the following text:

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

However, this case would be better solved using a custom-built parser. Regular expressions are not an effective solution to this problem, if you ask me.

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

text.split() with regex does the trick.

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);
发布评论

评论列表(0)

  1. 暂无评论