11

Is there any better solution to this here? I try to avoid the assignment inside while but still be able to loop through the matches and use the captured groups.

var match = "";
var CSS_URL_PATTERN = /url\s*\(\s*["|']?(.*?)\s*["|']?\)\s*/gm
while ((match = CSS_URL_PATTERN.exec(someBigCSSString)) !== null) {
   // Do stuff here per match…
}

I added a bit more context to this question, also a RegEx example.

5
  • 1
    Why not use match. It will return an array which you can loop. You way you designed it now will be an endless loop. Commented Aug 2, 2015 at 21:13
  • What are you trying to do in this loop? Commented Aug 2, 2015 at 21:14
  • "avoid the assignment inside while" - why? you can avoid it but it's really not that bad. Commented Aug 2, 2015 at 21:17
  • It won't work properly whether it has g flag. In this case, it should be assigned outside loop. Commented Aug 2, 2015 at 21:57
  • @dfsq Not sure about that. The only reason I can think of is that the assignment '=' can be easily misread with a comparison '==='. It simply doesn't feel right tbh and ESLint complains about it (no-cond-assign). Commented Aug 3, 2015 at 5:51

7 Answers 7

3

I always do as follows when I need .exec:

var re = /.../g, match;
while (match = re.exec(...)) {
    //...
}

Regular expressions with g flag causes infinite effect when it is in the loop condition.

What are the differences between Fx 3.x and Fx 4.x that made many userscripts stop working?

Sign up to request clarification or add additional context in comments.

2 Comments

Aye … I have the regex declaration outside of the loop. Amended my question for clarity.
@wittgenstein, my answer is still the same. I don't think there any better and shorter way to do what you want without missing legibility.
3

If you want to avoid the assignment inside while you can use a do while loop:

var URLRegExp = /url\s*\(\s*["|']?(.*?)\s*["|']?\)\s*/g
var match
do {
  match = URLRegExp.exec(bootstrap)
  if (match) {
    // Do stuff here per match...
  }
} while (match)

But a while loop it's simpler and avoids unnecesary code like the if statement inside do. An assignment inside a condition is not as bad as people think if you understand what's the behaviour of the code and what's the context.

Another case is when you're using a linter to avoid to mistype a comparison operator (such as ==) as an assignment operator, but allmost all the linters using now support using comments to modify linter behaviour in a specific part of the code so this isn't really a problem

1 Comment

nice! you can also break on no match if (!match) break;
1

In 2023 String.prototype.matchAll works as an alternative to the while loop:

const CSS_URL_PATTERN = /url\s*\(\s*["|']?(.*?)\s*["|']?\)\s*/gm
[...someBigCSSString.matchAll(CSS_URL_PATTERN)].forEach(match => {
  // Do stuff here per match…
});

Comments

0

var match = "Is This The Real Life|Is This Just Fantasy|Caught In A Landslide|No Escape From Reality|".match(/.+?\|/ig);

//print result using join
document.body.innerHTML += match.join("<br />");
document.body.innerHTML += "<br /><br />";
//print results using for loop and strip |
for (var i = 0; i < match.length; ++i)
{
    document.body.innerHTML += match[i].slice(0, -1) + "<br />";
}

This will avoid a loop altogether. match returns an array. You can either loop it and do stuff with it, or like I did print the results using join. match accepts regex-patterns.

Comments

0
var matches = someString.match(REGEX_PATTERN);
for (var i = 0; matches && i < matches.length; i++) {
  // Do stuff here per match…
}

3 Comments

If REGEX_PATTERN needs to capture groups and the global flag is set, you need to use RegExp.exec()
@w35l3y didn't realize that. TIL. The question says nothing about what he needs to do though...
@w35l3y Exactly. I added the regex to the question. Sorry, I missed it when I originally posted.
0
someString.replace(REGEX_PATTERN,
    function (wholeMatch, group1, group2/*...*/, index, sourceString) {
        // Do stuff here per match…
    });

Comments

0

A few years later...

const URLRegExp = /url\s*\(\s*["|']?(.*?)\s*["|']?\)\s*/g;
for (;;) {
  const match = URLRegExp.exec(bootstrap);
  if (!match) break;
    // Use the match
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.