简体   繁体   中英

Regexp, matching a word multiple times

This baffles me, though i suppose the problem is quite simple.

Given this piece of code:

var text   = ' url("https://") repeat scroll 0% 0%, url("https://") repeat scroll 0% 0%, url("https://") repeat scroll 0% 0% red';
var result = /(url)/.exec(text);

i get a result of ["url", "url"] ..where i would expect ["url", "url", "url"]

Any explanation why it's only catching 2 instances of url instead of 3

Thanks


Update for accepted answer

Actually this is part of a Modernizr function i'm rewriting for HeadJS, so the final function will be:

function multiplebgs() {
    var ele   = document.createElement('div');
    var style = ele.style;

    style.cssText = 'background:url(https://),url(https://),red url(https://)';

    // If the UA supports multiple backgrounds, there should be three occurrences
    // of the string "url(" in the return value for elemStyle.background
    var result = (style.background || "").match(/url/g);

    return Object.prototype.toString.call( result ) === '[object Array]' && result.length === 3;
}

And console.log(multiplebgs()); will now correctly return true on supported browsers.

If anyone sees additional problems with this, please leave a comment, thanks!

Use match with regular expression with g flag:

var text   = ' url("https://") repeat scroll 0% 0%, url("https://") repeat scroll 0% 0%, url("https://") repeat scroll 0% 0% red';
var result = (text || "").match(/url/g);
result // => ["url", "url", "url"]

Make your regex global and use match instead. You also do not need the capturing group.

var result = text.match(/url/g);

exec when used with the global flag will also allow you to get all matches, however exec is much more useful when you have multiple capturing groups. In your case to get all the matches with exec, you would have to do something like:

var matches = [],
    urlRx = /url/g,
    match;

while (match = urlRx.exec(text)) {
    matches.push(match[0]);
}

console.log(matches);

The second line is equivalent to your situation :

'url url url'.match(/url/)    // ["url"]
'url url url'.match(/(url)/)  // ["url", "url"]
'url url url'.match(/url/g)   // ["url", "url", "url"]
'url url url'.match(/(url)/g) // ["url", "url", "url"] same as previous line

Considering /(url)/ , what's inside parentheses is equivalent to a "sub regex" which is called a subpattern, or a group. Each group is captured the same way than the entire pattern, except when using the global flag ( //g ). In this case, groups are ignored and the entire pattern is captured as many times as it is found in the text. This example will be more explicit :

'hello world!hello world!'.match(/hello (world)(!)/)
// ["hello world!", "world", "!"]
// [entire pattern, group 1, group 2]

'hello world!hello world!'.match(/hello (world)(!)/g)
// ["hello world!", "hello world!"]
// [entire pattern, entire pattern]

Check this great resource about regular expressions in javascript : http://www.javascriptkit.com/javatutors/redev.shtml

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM