我确定它是4-8小时:-)最后(以及它的无用),这是编写正则表达式的一个很好的练习。你可以自由尝试。如果我们排除continue
的使用和Array
构造函数的使用,则完全可以使用jsLint。
var BuildRegex = function(matches) {
"use strict";
var splits = matches.split(','),
res = '^(',
i, subSplit, min, max, temp, tempMin;
if (splits.length === 0) {
return new RegExp('^()$');
}
for (i = 0; i < splits.length; i += 1) {
if (splits[i] === '*') {
return new RegExp('^([0-9]+)$');
}
subSplit = splits[i].split('-');
min = BuildRegex.Trim(subSplit[0], '0');
if (min === '') {
return null;
}
if (subSplit.length === 1) {
res += min;
res += '|';
continue;
} else if (subSplit.length > 2) {
return null;
}
max = BuildRegex.Trim(subSplit[1], '0');
if (max === '') {
return null;
}
if (min.length > max.length) {
return null;
}
// For 2-998 we first produce 2-9, then 10-99
temp = BuildRegex.DifferentLength(res, min, max);
tempMin = temp.min;
if (tempMin === null) {
return null;
}
res = temp.res;
// Then here 100-998
res = BuildRegex.SameLength(res, tempMin, max);
}
res = res.substr(0, res.length - 1);
res += ')$';
return new RegExp(res);
};
BuildRegex.Repeat = function(ch, n) {
"use strict";
return new Array(n + 1).join(ch);
};
BuildRegex.Trim = function(str, ch) {
"use strict";
var i = 0;
while (i < str.length && str[i] === ch) {
i += 1;
}
return str.substr(i);
};
BuildRegex.IsOnlyDigit = function(str, start, digit) {
"use strict";
var i;
for (i = start; i < str.length; i += 1) {
if (str[i] !== digit) {
return false;
}
}
return true;
};
BuildRegex.RangeDigit = function(min, max) {
"use strict";
if (min === max) {
return min;
}
return '[' + min + '-' + max + ']';
};
BuildRegex.DifferentLength = function(res, min, max) {
"use strict";
var tempMin = min,
i, tempMax;
for (i = min.length; i < max.length; i += 1) {
tempMax = BuildRegex.Repeat('9', i);
res = BuildRegex.SameLength(res, tempMin, tempMax);
tempMin = '1' + BuildRegex.Repeat('0', i);
}
if (tempMin > tempMax) {
return null;
}
return {
min: tempMin,
res: res
};
};
BuildRegex.SameLength = function(res, min, max) {
"use strict";
var commonPart;
// 100-100
if (min === max) {
res += min;
res += '|';
return res;
}
for (commonPart = 0; commonPart < min.length; commonPart += 1) {
if (min[commonPart] !== max[commonPart]) {
break;
}
}
res = BuildRegex.RecursivelyAddRange(res, min.substr(0, commonPart), min.substr(commonPart), max.substr(commonPart));
return res;
};
BuildRegex.RecursivelyAddRange = function(res, prefix, min, max) {
"use strict";
var only0Min, only9Max, i, middleMin, middleMax;
if (min.length === 1) {
res += prefix;
res += BuildRegex.RangeDigit(min[0], max[0]);
res += '|';
return res;
}
// Check if
only0Min = BuildRegex.IsOnlyDigit(min, 1, '0');
only9Max = BuildRegex.IsOnlyDigit(max, 1, '9');
if (only0Min && only9Max) {
res += prefix;
res += BuildRegex.RangeDigit(min[0], max[0]);
for (i = 1; i < min.length; i += 1) {
res += '[0-9]';
}
res += '|';
return res;
}
middleMin = min;
if (!only0Min) {
res = BuildRegex.RecursivelyAddRange(res, prefix + min[0], min.substr(1), BuildRegex.Repeat('9', min.length - 1));
if (min[0] !== '9') {
middleMin = String.fromCharCode(min.charCodeAt(0) + 1) + BuildRegex.Repeat('0', min.length - 1);
} else {
middleMin = null;
}
}
middleMax = max;
if (!only9Max) {
if (max[0] !== '0') {
middleMax = String.fromCharCode(max.charCodeAt(0) - 1) + BuildRegex.Repeat('9', max.length - 1);
} else {
middleMax = null;
}
}
if (middleMin !== null && middleMax !== null && middleMin[0] <= middleMax[0]) {
res = BuildRegex.RecursivelyAddRange(res, prefix + BuildRegex.RangeDigit(middleMin[0], middleMax[0]), middleMin.substr(1), middleMax.substr(1));
}
if (!only9Max) {
res = BuildRegex.RecursivelyAddRange(res, prefix + max[0], BuildRegex.Repeat('0', max.length - 1), max.substr(1));
}
return res;
};
// ----------------------------------------------------------
var printRegex = function(p) {
"use strict";
document.write(p + ': ' + BuildRegex(p) + '<br>');
};
printRegex('*');
printRegex('1');
printRegex('1,*');
printRegex('1,2,3,4');
printRegex('1,11-88');
printRegex('1,11-88,90-101');
printRegex('1-11111');
printRegex('75-11119');
这里测试http://jsfiddle.net/dnqYV/
C#的版本在这里http://ideone.com/3aEt3E
'/^[0,3-4] + $ /''的'0',''混合匹配3'和'4''像000,,, 34,000'。绝对不是你想要的。 – lkuty
'0,3-4' =>'/^[0,3-4] + $ /'是错误的。它将匹配33,44。正确的表达方式将会是'/ ^''/' – xanatos
做你想做的事情是可行的......但是它非常复杂。我会说半天/一天的工作。第一个提示是你必须用'|'替换''',基本表达式应该是'^(piece1 | piece2)$' – xanatos