正则
一个在Flash里面使用的正则表达式的类,使用这个类的原因是FLASH里面对文本输入检测要求不高,例如就不能检测输入的邮件格式是否正确;
class RegExp {
public var const:String = null;
public var source:String = null;
public var global:Boolean = false;
public var ignoreCase:Boolean = false;
public var multiline:Boolean = false;
public var lastIndex:Number = null;
public static var _xrStatic:Number = null;
public var _xr:Number = null;
public static var _xp:Number = null;
public static var _xxa:Array = null;
public static var _xxlp:Number = null;
public var _xq:Number = null;
public var _xqc:Number = null;
public static var d:Number = null;
public static var _xiStatic:Number = null;
public var _xi:Number = 0;
public static var _xxlm:String = null;
public static var _xxlc:String = null;
public static var _xxrc:String = null;
public static var lastMatch:String = null;
public static var leftContext:String = null;
public static var rightContext:String = null;
public static var _xa:Array = new Array();
public static var lastParen:String = null;
public static var _xaStatic:Array = new Array();
public static var $1:String = null;
public static var $2:String = null;
public static var $3:String = null;
public static var $4:String = null;
public static var $5:String = null;
public static var $6:String = null;
public static var $7:String = null;
public static var $8:String = null;
public static var $9:String = null;
private static var _setString:Boolean = RegExp.setStringMethods();
function RegExp() {
if (arguments[0] == null) {
} else {
const = "RegExp";
compile.apply(this, arguments);
}
}
public function invStr(sVal:String):String {
var s = sVal;
var l = length(s);
var j;
var c;
var r = "";
for (var i = 1; i<255; i++) {
c = chr(i);
j = 0;
while (j<=l && substring(s, 1+j++, 1) != c) {
}
if (j>l) {
r += c;
}
}
return s;
}
public function compile() {
this.source = arguments[0];
if (arguments.length>1) {
var flags = (arguments[1]+’’).toLowerCase();
for (var i = 0; i<length(flags); i++) {
if (substring(flags, i+1, 1) == "g") {
this.global = true;
}
if (substring(flags, i+1, 1) == "i") {
this.ignoreCase = true;
}
if (substring(flags, i+1, 1) == "m") {
this.multiline = true;
}
}
}
if (arguments.length < 3) {
var root = true;
RegExp._xrStatic = 1;
//Paren counter
var i = 0;
} else {
var root = false;
this._xr = RegExp._xrStatic++;
var i = arguments[2];
}
this.lastIndex = 0;
/*
Compile the regular expression
The array of character definition objects will be created:
q[n].t --> type of match required: 0 = exact
1 = in char set
2 = not in char set
3 = paren
4 = ref to paren
7 = new "OR" section
9 = beginning of line
10 = end of line
q[n].s --> character or character set
q[n].a --> character has to repeat at least a times
q[n].b --> character has to repeat at most b times
*/
var re = this.source;
var ex;
var l = length(re);
var q = [];
var qc = 0;
var s;
var range = false;
var ca;
var cb;
var atEnd = false;
var char;
for (i=i; i<l; ++i) {
var thischar = substring(re, i+1, 1);
if (thischar == "\\") {
i++;
char = false;
thischar = substring(re, i+1, 1);
} else {
char = true;
}
var nextchar = substring(re, i+2, 1);
q[qc] = new Object();
q[qc].t = 0;
q[qc].a = 0;
q[qc].b = 999;
q[qc].c = -10;
if (char) {
// Handle special characters
if (thischar == "(") {
//Opening paren
ex = new RegExp(re, (this.ignoreCase ? "gi" : "g"), i+1);
i = RegExp._xiStatic;
q[qc].t = 3;
thischar = ex;
nextchar = substring(re, i+2, 1);
} else if (!root && thischar == ")") {
//Closing paren
break;
} else if (thischar == "^") {
//Must be located at the beginning of string/line
if (qc == 0 || q[qc-1].t == 7) {
q[qc].t = 9;
q[qc].a = 1;
q[qc].b = 1;
qc++;
}
continue;
} else if (thischar == "$") {
//Must be located at the end of string/line
if (root) {
atEnd = true;
}
continue;
} else if (thischar == "[") {
//This is a character set
i++;
if (nextchar == "^") {
q[qc].t = 2;
i++;
} else {
q[qc].t = 1;
}
thischar = "";
range = false;
while (i<l && (s=substring(re, 1+i++, 1)) != "]") {
if (range) {
//Previous char was "-", so create a range
if (s == "\\") {
}
cb = s == "\\" ? (s == "b" ? chr(8) : substring(re, 1+i++, 1)) : s;
ca = ord(substring(thischar, length(thischar), 1))+1;
while (cb>=(s=chr(ca++))) {
thischar += s;
}
range = false;
} else {
if (s == "-" && length(thischar)>0) {
//Character range is being defined
range = true;
} else {
if (s == "\\") {
//Predefined char set may follow
s = substring(re, 1+i++, 1);
if (s == "d") {
thischar += "0123456789";
} else if (s == "D") {
thischar += invStr("0123456789");
} else if (s == "s") {
thischar += " \f\n\r\t\v";
} else if (s == "S") {
thischar += invStr(" \f\n\r\t\v");
} else if (s == "w") {
thischar += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
} else if (s == "W") {
thischar += invStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
} else if (s == "b") {
thischar += chr(8);
} else if (s == "\\") {
thischar += s;
}
} else {
thischar += s;
}
}
}
}
if (range) thischar += "-";
i--;
var nextchar = substring(re, i+2, 1);
} else if (thischar == "|") {
//OR section
if (atEnd) {
q[qc].t = 10;
q[qc].a = 1;
q[qc].b = 1;
qc++;
q[qc] = new Object();
atEnd = false;
}
q[qc].t = 7;
q[qc].a = 1;
q[qc].b = 1;
qc++;
continue;
} else if (thischar == ".") {
q[qc].t = 2;
thischar = "\n";
} else if (thischar == "*" || thischar == "?" || thischar == "+") {
continue;
}
} else {
if (thischar>="1" && thischar<="9") {
q[qc].t = 4;
} else if (thischar == "b") {
q[qc].t = 1;
thischar = "--wb--";
} else if (thischar == "B") {
q[qc].t = 2;
thischar = "--wb--";
} else if (thischar == "d") {
q[qc].t = 1;
thischar = "0123456789";
} else if (thischar == "D") {
q[qc].t = 2;
thischar = "0123456789";
} else if (thischar == "s") {
q[qc].t = 1;
thischar = " \f\n\r\t\v";
} else if (thischar == "S") {
q[qc].t = 2;
thischar = " \f\n\r\t\v";
} else if (thischar == "w") {
q[qc].t = 1;
thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
} else if (thischar == "W") {
q[qc].t = 2;
thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
}
}
//Counting metacharacters
if (nextchar == "*") {
q[qc].s = thischar;
qc++;
i++;
} else if (nextchar == "?") {
q[qc].s = thischar;
q[qc].b = 1;
qc++;
i++;
} else if (nextchar == "+") {
q[qc].s = thischar;
q[qc].a = 1;
qc++;
i++;
} else if (nextchar == "{") {
var comma = false;
var rangeA = 0;
range = "";
i++;
while (i+1<l && (s=substring(re, 2+i++, 1)) != "}") {
if (!comma && s == ",") {
comma = true;
rangeA = Number(range);
rangeA = Math.floor(isNaN(rangeA) ? 0 : rangeA);
if (rangeA<0) {
rangeA = 0;
}
range = "";
} else {
range += s;
}
}
var rangeB = Number(range);
rangeB = Math.floor(isNaN(rangeB) ? 0 : rangeB);
if (rangeB<1) {
rangeB = 999;
}
if (rangeB<rangeA) {
rangeB = rangeA;
}
q[qc].s = thischar;
q[qc].b = rangeB;
q[qc].a = comma ? rangeA : rangeB;
qc++;
} else {
q[qc].s = thischar;
q[qc].a = 1;
q[qc].b = 1;
qc++;
}
}
if (root && atEnd) {
q[qc] = new Object();
q[qc].t = 10;
q[qc].a = 1;
q[qc].b = 1;
qc++;
}
if (!root) {
RegExp._xiStatic = i;
this.source = substring(re, arguments[2]+1, i-arguments[2]);
}
if (RegExp.d) {
for (var i = 0; i<qc; i++) {
trace("xr"+this._xr+’ ’+q[i].t+" : "+q[i].a+" : "+q[i].b+" : "+q[i].s);
}
}
this._xq = q;
this._xqc = qc;
RegExp._xp = 0;
}
public function test() {
if (RegExp._xp++ == 0) {
RegExp._xxa = [];
//Temp array for storing paren matches
RegExp._xxlp = 0;
//Last paren
}
// q[n].c --> count of matches
// q[n].i --> index within the string
var str = arguments[0]+’’;
var re;
var q = this._xq;
var qc = this._xqc;
var qb;
var c;
var cl;
var ct;
var s;
var l = length(str);
var ix = this.global ? this.lastIndex : 0;
var ix_ = ix;
var str_ = str;
if (this.ignoreCase) {
str = str.toLowerCase();
}
var r = new Object();
r.i = -1;
var i = -1;
while (i<qc-1) {
i++;
if (RegExp.d) {
trace("New section started at i="+i);
}
ix = ix_;
qb = i;
q[qb].c = -10;
var atEnd = false;
while (i>qb || ix<l+1) {
if (q[i].t == 7) {
//New "OR" section coming
break;
} else if (q[i].t == 9) {
i++;
if (i == qb+1) {
var atStart = true;
qb = i;
}
q[qb].c = -10;
continue;
} else {
if (r.i>=0 && ix>=r.i) {
//There is already better match, so quit searching
break;
}
if (q[i].c == -10) {
if (RegExp.d) {
trace("Lookup #"+i+" at index "+ix+" for \\\\\\\\\\\\\\\\’"+q[i].s+"\\\\\\\\\\\\\\\\’ type "+q[i].t);
}
//Count the # of matches
var m = 0;
q[i].i = ix;
if (q[i].t == 0) {
//Exact match
c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
while (m<q[i].b && ix<l) {
if (substring(str, 1+ix, 1) == c) {
m++;
ix++;
} else {
break;
}
}
} else if (q[i].t == 1) {
//In char set
if (q[i].s == "--wb--") {
q[i].a = 1;
if (ix>0 && ix<l) {
ct = substring(str, ix, 1);
if (ct == " " || ct == "\\\\\\\\\\\\\\\\n") {
m = 1;
}
if (m == 0) {
ct = substring(str, 1+ix, 1);
if (ct == " " || ct == "\\\\\\\\\\\\\\\\n") {
m = 1;
}
}
} else {
m = 1;
}
} else {
c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
cl = length(c);
var cs;
while (m<q[i].b && ix<l) {
ct = substring(str, 1+ix, 1);
cs = 0;
while (cs<=cl && substring(c, 1+cs++, 1) != ct) {
}
if (cs<=cl) {
m++;
ix++;
} else {
break;
}
}
}
} else if (q[i].t == 2) {
//Not in char set
c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
cl = length(c);
if (q[i].s == "--wb--") {
q[i].a = 1;
if (ix>0 && ix<l) {
ct = substring(str, ix, 1);
s = substring(str, 1+ix, 1);
if (ct != " " && ct != "\\\\\\\\\\\\\\\\n" && s != " " && s != "\\\\\\\\\\\\\\\\n") {
m = 1;
}
} else {
m = 0;
}
} else {
while (m<q[i].b && ix<l) {
ct = substring(str, 1+ix, 1);
cs = 0;
while (cs<=cl && substring(c, 1+cs++, 1) != ct) {
}
if (cs<=cl) {
break;
} else {
m++;
ix++;
}
}
}
} else if (q[i].t == 10) {
//End of string/line must be next
s = substring(str, 1+ix, 1);
m = (this.multiline && (s == "\\\\\\\\\\\\\\\\n" || s == "\\\\\\\\\\\\\\\\r")) || ix == l ? 1 : 0;
} else if (q[i].t == 3) {
//Regular expression in parens
re = q[i].s;
q[i].ix = [];
q[i].ix[m] = ix;
//Save index if need to retreat
re.lastIndex = ix;
while (m<q[i].b && re.test(str_)) {
cl = length(RegExp._xxlm);
if (cl>0) {
ix += cl;
m++;
q[i].ix[m] = ix;
} else {
m = q[i].a;
q[i].ix[m-1] = ix;
break;
}
}
if (m == 0) {
RegExp._xxlm = "";
}
if (re._xr>RegExp._xxlp) {
RegExp._xxlp = re._xr;
}
RegExp._xxa[Number(re._xr)] = RegExp._xxlm;
} else if (q[i].t == 4) {
//Back reference to paren
if (RegExp._xp>=(c=Number(q[i].s))) {
c = RegExp._xxa[c];
c = this.ignoreCase ? c.toLowerCase() : c;
cl = length(c);
q[i].ix = [];
q[i].ix[m] = ix;
if (cl>0) {
while (m<q[i].b && ix<l) {
if (substring(str, 1+ix, cl) == c) {
m++;
ix += cl;
q[i].ix[m] = ix;
} else {
break;
}
}
} else {
m = 0;
q[i].a = 0;
}
} else {
//Paren is not ready, treat number as charcode
c = chr(c);
q[i].ix = [];
q[i].ix[m] = ix;
while (m<q[i].b && ix<l) {
if (substring(str, 1+ix, 1) == c) {
m++;
ix++;
q[i].ix[m] = ix;
} else {
break;
}
}
}
}
q[i].c = m;
if (RegExp.d) {
trace(" "+m+" matches found");
}
}
if (q[i].c<q[i].a) {
if (RegExp.d) {
trace(" not enough matches");
}
//Not enough matches
if (i>qb) {
//Retreat back and decrease # of assumed matches
i--;
q[i].c--;
if (q[i].c>=0) {
ix = (q[i].t == 3 || q[i].t == 4) ? q[i].ix[q[i].c] : (q[i].i+q[i].c);
}
if (RegExp.d) {
trace("Retreat to #"+i+" c="+q[i].c+" index="+ix);
}
} else {
if (RegExp._xp>1) {
//If this is a paren, failing to find first match is fatal
break;
}
if (atStart) {
//Match must be at the start of string/line
if (this.multiline) {
//Jump to the beginning of the next line
while (ix<=l) {
s = substring(str, 1+ix++, 1);
if (s == "\\\\\\\\\\\\\\\\n" || s == "\\\\\\\\\\\\\\\\r") {
break;
}
}
q[i].c = -10;
} else {
//No match
break;
}
} else {
//Start a new search from next position
ix++;
q[i].c = -10;
}
}
} else {
if (RegExp.d) {
trace(" enough matches!");
}
//# of matches ok, proceed to next
i++;
if (i == qc || q[i].t == 7) {
if (RegExp.d) {
trace("Saving better result: r.i = q["+qb+"].i = "+q[qb].i);
}
r.i = q[qb].i;
r.li = ix;
break;
} else {
q[i].c = -10;
}
}
}
}
while (i<qc && q[i].t != 7) {
i++;
}
//Jump to the next "OR" section
}
if (r.i<0) {
this.lastIndex = 0;
if (RegExp._xp-- == 1) {
RegExp._xxa = [];
RegExp._xxlp = 0;
}
return false;
} else {
ix = r.li;
this._xi = r.i;
RegExp._xxlm = substring(str_, r.i+1, ix-r.i);
RegExp._xxlc = substring(str_, 1, r.i);
RegExp._xxrc = substring(str_, ix+1, l-ix);
if (ix == r.i) {
ix++;
}
this.lastIndex = ix;
if (RegExp._xp-- == 1) {
RegExp.lastMatch = RegExp._xxlm;
RegExp.leftContext = RegExp._xxlc;
RegExp.rightContext = RegExp._xxrc;
RegExp._xaStatic = RegExp._xxa;
RegExp.lastParen = RegExp._xxa[Number(RegExp._xxlp)];
for (i=1; i<10; i++) {
RegExp["$"+i] = RegExp._xaStatic[Number(i)];
}
}
return true;
}
}
public function exec() {
var str = arguments[0]+’’;
if (str == ’’) {
return false;
}
var t = this.test(str);
if (t) {
var ra = new Array();
ra.index = this._xi;
ra.input = str;
ra[0] = RegExp.lastMatch;
var l = RegExp._xaStatic.length;
for (var i = 1; i<l; i++) {
ra[i] = RegExp._xaStatic[Number(i)];
}
} else {
var ra = null;
}
return ra;
}
public static function setStringMethods() {
if(String.prototype.match != undefined) {
return;
}
String.prototype.match = function() {
if (typeof (arguments[0]) != "object") {
return null;
}
if (arguments[0].const != "RegExp") {
return null;
}
var re = arguments[0];
var s = this.valueOf();
var ip = 0;
var rc = 0;
if (re.global) {
re.lastIndex = 0;
while (re.test(s)) {
if (rc == 0) {
var ra = new Array();
}
ra[rc++] = RegExp.lastMatch;
ip = re.lastIndex;
}
re.lastIndex = ip;
} else {
var ra = re.exec(s);
rc++;
}
return (rc == 0) ? null : ra;
};
String.prototype.replace = function() {
if (typeof (arguments[0]) != "object") {
return null;
}
if (arguments[0].const != "RegExp") {
return null;
}
var re = arguments[0];
var rs = arguments[1]+’’;
var s = this;
var r = "";
re.lastIndex = 0;
if (re.global) {
var ip = 0;
var ix = 0;
while (re.test(s)) {
//Replace backreferences in rs
var i = 0;
var l = length(rs);
var c = "";
var pc = "";
var nrs = "";
while (i<l) {
c = substring(rs, 1+i++, 1);
if (c == "$" && pc != "\\") {
c = substring(rs, 1+i++, 1);
if (isNaN(Number(c)) || Number(c)>9) {
nrs += "$"+c;
} else {
nrs += RegExp._xaStatic[Number(c)];
}
} else {
nrs += c;
}
pc = c;
}
r += substring(s, ix+1, re._xi-ix)+nrs;
ix = re._xi+length(RegExp.lastMatch);
ip = re.lastIndex;
}
re.lastIndex = ip;
} else {
if (re.test(s)) {
r += RegExp.leftContext+rs;
}
}
r += re.lastIndex == 0 ? s : RegExp.rightContext;
return r;
};
String.prototype.search = function() {
if (typeof (arguments[0]) != "object") {
return null;
}
if (arguments[0].const != "RegExp") {
return null;
}
var re = arguments[0];
var s = this;
re.lastIndex = 0;
var t = re.test(s);
return t ? re._xi : -1;
};
String.prototype.old_split = String.prototype.split;
String.prototype.split = function() {
if (typeof (arguments[0]) == "object" && arguments[0].const == "RegExp") {
var re = arguments[0];
var lm = arguments[1] == null ? 9999 : Number(arguments[1]);
if (isNaN(lm)) {
lm = 9999;
}
var s = this;
var ra = new Array();
var rc = 0;
var gs = re.global;
re.global = true;
re.lastIndex = 0;
var ip = 0;
var ipp = 0;
var ix = 0;
while (rc<lm && re.test(s)) {
//trace(re._xi + " " + ix + " " + RegExp.lastMatch);
if (re._xi != ix) {
ra[rc++] = substring(s, ix+1, re._xi-ix);
}
ix = re._xi+length(RegExp.lastMatch);
ipp = ip;
ip = re.lastIndex;
}
if (rc == lm) {
re.lastIndex = ipp;
} else {
re.lastIndex = ip;
}
if (rc == 0) {
ra[rc] = s;
} else {
if (rc<lm && length(RegExp.rightContext)>0) {
ra[rc++] = RegExp.rightContext;
}
}
re.global = gs;
return ra;
} else {
return this.old_split(arguments[0], arguments[1]);
}
};
return true;
}
} 范例:
var re = new RegExp("\w{3}", "i");
trace(re.test("ABC"));