When I run the code below in debug mode I get the expected value on the first iteration of the for loop but null on the second as seen on the images:
First iteration:
Second iteration:
What am I dong wrong?
The code I am using is:
var newer_than = ' newer_than:2d'; //added for faster debugging
var subjectIdentifier = '"Ingress Portal Submitted: "';
var searchString = 'subject:'+subjectIdentifier+newer_than;
function getPortalName(string) {
var myRegexp = /: (.+)/g;
var match = myRegexp.exec(string);
var portalName = match[1];
return portalName;
}
function getPortalsSubmitted() {
var threads = GmailApp.search(searchString);
for (i=0; i<threads.length; i++) {
var subject = threads[i].getFirstMessageSubject();
var portalName = getPortalName(subject);
var subDate = threads[i].getMessages()[0].getDate();
Logger.log([portalName,subDate]);
}
}
function updatePortals() {
var threads = GmailApp.search('subject:"Ingress Portal"');
for (i=0; i<threads.length; i++) {
Logger.log(threads[i].getFirstMessageSubject());
}
}
When I run the code below in debug mode I get the expected value on the first iteration of the for loop but null on the second as seen on the images:
First iteration:
Second iteration:
What am I dong wrong?
The code I am using is:
var newer_than = ' newer_than:2d'; //added for faster debugging
var subjectIdentifier = '"Ingress Portal Submitted: "';
var searchString = 'subject:'+subjectIdentifier+newer_than;
function getPortalName(string) {
var myRegexp = /: (.+)/g;
var match = myRegexp.exec(string);
var portalName = match[1];
return portalName;
}
function getPortalsSubmitted() {
var threads = GmailApp.search(searchString);
for (i=0; i<threads.length; i++) {
var subject = threads[i].getFirstMessageSubject();
var portalName = getPortalName(subject);
var subDate = threads[i].getMessages()[0].getDate();
Logger.log([portalName,subDate]);
}
}
function updatePortals() {
var threads = GmailApp.search('subject:"Ingress Portal"');
for (i=0; i<threads.length; i++) {
Logger.log(threads[i].getFirstMessageSubject());
}
}
Share
Improve this question
asked Jun 6, 2013 at 12:21
LucianoLuciano
1,0721 gold badge11 silver badges18 bronze badges
11
-
1
Yes, it shouldn't have been an issue. Can you replace this pattern with more generic
/:\s*(.+)/g
? And still, I'd have usedsplit
here, by something likereturn string.split(/:\s*/)[1];
probably. – raina77ow Commented Jun 6, 2013 at 12:33 -
1
Now that's weird. Indeed, that behavior is explainable if regexobject was the same all the time - but it's clearly not. Well, can you check this by removing
/g
modifier from the pattern? It's not required here anyway. – raina77ow Commented Jun 6, 2013 at 13:54 - 1 Should I make it an answer? Actually, @FabrícioMatté already had one. ) – raina77ow Commented Jun 6, 2013 at 14:23
-
1
@raina77ow Feel free to answer if you can, I'll be a little busy in the next hours and I don't really like making up explanations.
:P
– Fabrício Matté Commented Jun 6, 2013 at 14:39 -
2
You're using a regex literal, so you're not creating the regex everytime. Literals don't have scope. And here is the documentation on the
g
flag behavior. – Henrique G. Abreu Commented Jun 7, 2013 at 14:54
1 Answer
Reset to default 14Although this question was already answered on the ments, I'll make a proper answer.
One important issue to understand this problem is on the exec
behavior when the regex have the g
flag. Which, when called sequentially will try to look for the "next" match, even if you pass on a different string. Here is the documentation link on MDN.
And although MDN states that you should take care not to re-create the RegExp object (even a literal), because it might reset the lastIndex
property. At least in Apps Script that's not true. If a regex literal is used in the exact same spot in the code over and over, Apps Script caches the regex and re-uses the same object.
This two effects bined meant you were triggering this "next match" behavior on your code unknowingly.
The easiest solution for you is to just drop the g
flag, since you don't need it anyway (you're getting only the first result). But you could have also fixed this by replacing the var myRegexp = /: (.+)/g;
line with var myRegexp = new RegExp(': (.+)','g');
, forcing Apps Script to give you a new object.
I think a good lesson we can learn from this is: don't use a flag if you don't need it. Sometimes we're lazy and set flags without thinking, "just in case".