Javascript正则expression式,用于显示六位数的base36数字

我构build了一个node.js应用程序,并在Mongodb中存储了一个六位数的unix时间戳(以秒为单位)的base36表示,作为_id的第一部分。 一个典型的_id看起来像这样:

"_id" : "lwhlzy/czwszasfgr/a4d18976c1/f835caa1c3/184d06b47f" 

几条数据连接在一起,包括时间戳,后面跟着一系列散列数据,形成一个GUID和一个“ 物化path ”

稍后的查询将根据时间范围selectlogging,然后是获取特定path期间发生的事件的path。 这些查询将依赖于根的正则expression式 ,所以我需要一个正则expression式,可以find一个base36数字的范围:

这是我到目前为止的代码(通过节点运行testing,是的,它被硬编码为六位数字,第七位数字将不需要,直到2038年12月23日)。

 var base36 = "0123456789abcdefghijklmnopqrstuvwxyz"; // determine how many left-most characters from & to have in common // this function works nicely, no problems here var getOverlap = function (from, to) { regex = ''; count = to.length; for (i in to) { regex += (i>0?'|':'')+'('+to.slice(0,count)+')'; count--; } result = from.match(RegExp(regex,"ig")); return result[0]; }; var from = "lec0s0"; var to = "lwhvqg"; // generated from: parseInt(Date.now()/1000,10).toString(36) var overlap = getOverlap(from,to); console.log(from); console.log(to); var regex = overlap; var i = overlap.length; // start immediately after the left-most common characters and append the rest of the regex while (i<6) { regex += "["; if (from[i] < to[i]) { regex += base36.slice(base36.indexOf(from[i]), base36.indexOf(to[i])+1); } else { regex += base36.slice(base36.indexOf(from[i])) + base36.slice(0, base36.indexOf(to[i])+1); } regex += "]"; i++; } console.log(regex); process.exit(); 

这将输出这样的东西:

 l[efghijklmnopqrstuvw][cdefgh][0123456789abcdefghijklmnopqrstuv][stuvwxyz0123456789abcdefghijklmnopq][0123456789abcdefg] 

经过研究,我意识到有两个主要的问题:1)对于一个真正的范围它不是很正确(它会跳过大量的logging),2)而是像[ew]而不是每个字符明确声明尽pipe它仍然有效。

对于from="lec0s0"to="lwhvqg"input,我意识到我错过了这个正则expression式的很大一部分。 例如,上面的代码只允许第三个字符从ch ,但是在第二个字符可以递增之前,这个位置需要达到“z”。 我已经确定,我实际上需要一个正则expression式,看起来更像这样:

 l[ev][0-9a-z][0-9a-z][0-9a-z][0-9a-z]|l[ew][cg][0-9a-z][0-9a-z][0-9a-z]|l[ew][ch][0-9a-u][0-9a-z][0-9a-z]|l[ew][ch][0-9a-v][0-9a-o][0-9a-z]|l[ew][ch][0-9a-v][0-9a-q][0-9a-g] 

所以我的问题是:我是否有理由认为正则expression式需要像上面的那样? 如果是这样,我该如何修改代码来生成它?

提前致谢!

您目前的模式将从le0000和以上匹配,您实际上希望匹配:

 lec0s[0-9a-z]|lec0[tz][0-9a-z]{1}|lec[1-9a-z][0-9a-z]{2}|le[dz][0-9a-z]{3}|l[fv][0-9a-z]{4}|lw[0-9a-g][0-9a-z]{3}|lwh[0-9a-u][0-9a-z]{2}|lwhv[0-9a-p][0-9a-z]{1}|lwhvq[0-9a-g] 

下面的函数应该给你你需要的正则expression式:

 function getRegex(from,to) { var base36 = '0123456789abcdefghijklmnopqrstuvwxyz', getRange = function(f,t) { if(f == t) { return f; } if(base36.indexOf(f) >= base36.indexOf(t)) { return t; } if(t <= '9' || f >= 'a'){ return '[' +f+'-'+t+']'; } return '[' +f+(f<'9'?'-9':'')+(t>'a'?'a-':'')+t+']'; }, from = from.split(''), to = to.split(''), prefix='', regex=[], tmp,i,l; for(i=0,l=from.length;i<l;i++) { if(from[i]!=to[i]) { break; } prefix+=from[i]; } from.splice(0,prefix.length); to.splice(0,prefix.length); i = from.length; while(i--) { tmp = prefix+from.slice(0,i).join(''); if(from[i] == 'z') { tmp+='z'; } else if(from.length-i == 1) { tmp += getRange(from[i],'z'); } else if(i) { tmp += getRange(base36.charAt(base36.indexOf(from[i])+1),'z'); tmp += '[0-9a-z]{'+(from.length-i-1)+'}'; } else { tmp += getRange(base36.charAt(base36.indexOf(from[i])+1),base36.charAt(base36.indexOf(to[i])-1)); tmp += '[0-9a-z]{'+(from.length-i-1)+'}'; } regex.push(tmp); } for(i=1,l=to.length;i<l;i++) { tmp = prefix+to.slice(0,i).join(''); if(to[i] == '0') { tmp+='0'; } else if(to.length-i == 1) { tmp += getRange('0',to[i]); } else { tmp += getRange('0',base36.charAt(base36.indexOf(to[i])-1)); tmp += '[0-9a-z]{'+(from.length-i-1)+'}'; } regex.push(tmp); } return regex.join('|'); } 

你可以在这里看到它: http : //jsfiddle.net/3cu52/3/

我只想指出你的模式中的一个错误

 l[ev][0-9a-z][0-9a-z][0-9a-z][0-9a-z]|l[ew][cg][0-9a-z][0-9a-z][0-9a-z]|l[ew][ch][0-9a-u][0-9a-z][0-9a-z]|l[ew][ch][0-9a-v][0-9a-o][0-9a-z]|l[ew][ch][0-9a-v][0-9a-q][0-9a-g] l[ev][0-9a-z][0-9a-z][0-9a-z][0-9a-z]|lw[cg][0-9a-z][0-9a-z][0-9a-z]|lwh[0-9a-u][0-9a-z][0-9a-z]| ... ^ ^^ 

在标记的位置,你不需要重复范围,这是不必要的,因为你在第一个select中覆盖了以“le”开头的模式。