/*
用途:校验ip地址的格式
输入:strIP:ip地址
返回:如果通过验证返回true,否则返回false;
*/
function isIP(strIP) {
if (isNull(strIP)) return false;
var re=/^(/d+)/.(/d+)/.(/d+)/.(/d+)$/g //匹配IP地址的正则表达式
if(re.test(strIP))
{
if( RegExp.$1 <256 && RegExp.$2<256 && RegExp.$3<256 && RegExp.$4<256) return true;
}
return false;
}
/*
用途:检查输入字符串是否为空或者全部都是空格
输入:str
返回:
如果全是空返回true,否则返回false
*/
function isNull( str ){
if ( str == "" ) return true;
var regu = "^[ ]+$";
var re = new RegExp(regu);
return re.test(str);
}
/*
用途:检查输入对象的值是否符合整数格式
输入:str 输入的字符串
返回:如果通过验证返回true,否则返回false
*/
function isInteger( str ){
var regu = /^[-]{0,1}[0-9]{1,}$/;
return regu.test(str);
}
/*
用途:检查输入手机号码是否正确
输入:
s:字符串
返回:
如果通过验证返回true,否则返回false
*/
function checkMobile( s ){
var regu =/^[1][3][0-9]{9}$/;
var re = new RegExp(regu);
if (re.test(s)) {
return true;
}else{
return false;
}
}
/*
用途:检查输入字符串是否符合正整数格式
输入:
s:字符串
返回:
如果通过验证返回true,否则返回false
*/
function isNumber( s ){
var regu = "^[0-9]+$";
var re = new RegExp(regu);
if (s.search(re) != -1) {
return true;
} else {
return false;
}
}
/*
用途:检查输入字符串是否是带小数的数字格式,可以是负数
输入:
s:字符串
返回:
如果通过验证返回true,否则返回false
*/
function isDecimal( str ){
if(isInteger(str)) return true;
var re = /^[-]{0,1}(/d+)[/.]+(/d+)$/;
if (re.test(str)) {
if(RegExp.$1==0&&RegExp.$2==0) return false;
return true;
} else {
return false;
}
}
/*
用途:检查输入对象的值是否符合端口号格式
输入:str 输入的字符串
返回:如果通过验证返回true,否则返回false
*/
function isPort( str ){
return (isNumber(str) && str<65536);
}
/*
用途:检查输入对象的值是否符合E-Mail格式
输入:str 输入的字符串
返回:如果通过验证返回true,否则返回false
*/
function isEmail( str ){
var myReg = /^[-_A-Za-z0-9]+@([_A-Za-z0-9]+/.)+[A-Za-z0-9]{2,3}$/;
if(myReg.test(str)) return true;
return false;
}
/*
用途:检查输入字符串是否符合金额格式
格式定义为带小数的正数,小数点后最多三位
输入:
s:字符串
返回:
如果通过验证返回true,否则返回false
*/
function isMoney( s ){
var regu = "^[0-9]+[/.][0-9]{0,3}$";
var re = new RegExp(regu);
if (re.test(s)) {
return true;
} else {
return false;
}
}
/*
用途:检查输入字符串是否只由英文字母和数字和下划线组成
输入:
s:字符串
返回:
如果通过验证返回true,否则返回false
*/
function isNumberOr_Letter( s ){//判断是否是数字或字母
var regu = "^[0 -9a -zA-Z/_]+$";
var re = new RegExp(regu);
if (re.test(s)) {
return true;
}else{
return false;
}
}
/*
用途:检查输入字符串是否只由英文字母和数字组成
输入:
s:字符串
返回:
如果通过验证返回true,否则返回false
*/
function isNumberOrLetter( s ){//判断是否是数字或字母
var regu = "^[0 -9a -zA-Z]+$";
var re = new RegExp(regu);
if (re.test(s)) {
return true;
}else{
return false;
}
}
/*
用途:检查输入字符串是否只由汉字、字母、数字组成
输入:
value:字符串
返回:
如果通过验证返回true,否则返回false
*/
function isChinaOrNumbOrLett( s ){//判断是否是汉字、字母、数字组成
var regu = "^[0 -9a -zA-Z/u4e00-/u9fa5]+$";
var re = new RegExp(regu);
if (re.test(s)) {
return true;
}else{
return false;
}
}
/*
用途:判断是否是日期
输入:date:日期;fmt:日期格式
返回:如果通过验证返回true,否则返回false
*/
function isDate( date, fmt ) {
if (fmt==null) fmt="yyyyMMdd";
var yIndex = fmt.indexOf("yyyy");
if(yIndex==-1) return false;
var year = date.substring(yIndex,yIndex+4);
var mIndex = fmt.indexOf("MM");
if(mIndex==-1) return false;
var month = date.substring(mIndex,mIndex+2);
var dIndex = fmt.indexOf("dd");
if(dIndex==-1) return false;
var day = date.substring(dIndex,dIndex+2);
if(!isNumber(year)||year>"2100" || year< "1900") return false;
if(!isNumber(month)||month>"12" || month< "01") return false;
if(day>getMaxDay(year,month) || day< "01") return false;
return true;
}
function getMaxDay(year,month) {
if(month==4||month==6||month==9||month==11)
return "30";
if(month==2)
if(year%4==0&&year%100!=0 || year%400==0)
return "29";
else
return "28";
return "31";
}
/*
用途:字符1是否以字符串2结束
输入:str1:字符串;str2:被包含的字符串
返回:如果通过验证返回true,否则返回false
*/
function isLastMatch(str1,str2)
{
var index = str1.lastIndexOf(str2);
if(str1.length==index+str2.length) return true;
return false;
}
/*
用途:字符1是否以字符串2开始
输入:str1:字符串;str2:被包含的字符串
返回:如果通过验证返回true,否则返回false
*/
function isFirstMatch(str1,str2)
{
var index = str1.indexOf(str2);
if(index==0) return true;
return false;
}
/*
用途:字符1是包含字符串2
输入:str1:字符串;str2:被包含的字符串
返回:如果通过验证返回true,否则返回false
*/
function isMatch(str1,str2)
{
var index = str1.indexOf(str2);
if(index==-1) return false;
return true;
}
/*
用途:检查输入的起止日期是否正确,规则为两个日期的格式正确,
且结束如期>=起始日期
输入:
startDate:起始日期,字符串
endDate:结束如期,字符串
返回:
如果通过验证返回true,否则返回false
*/
function checkTwoDate( startDate,endDate ) {
if( !isDate(startDate) ) {
alert("起始日期不正确!");
return false;
} else if( !isDate(endDate) ) {
alert("终止日期不正确!");
return false;
} else if( startDate > endDate ) {
alert("起始日期不能大于终止日期!");
return false;
}
return true;
}
/*
用途:检查输入的Email信箱格式是否正确
输入:
strEmail:字符串
返回:
如果通过验证返回true,否则返回false
*/
function checkEmail(strEmail) {
//var emailReg = /^[_a-z0-9]+@([_a-z0-9]+/.)+[a-z0-9]{2,3}$/;
var emailReg = /^[/w-]+(/.[/w-]+)*@[/w-]+(/.[/w-]+)+$/;
if( emailReg.test(strEmail) ){
return true;
}else{
alert("您输入的Email地址格式不正确!");
return false;
}
}
/*
用途:检查输入的电话号码格式是否正确
输入:
strPhone:字符串
返回:
如果通过验证返回true,否则返回false
*/
function checkPhone( strPhone ) {
var phoneRegWithArea = /^[0][1-9]{2,3}-[0-9]{5,10}$/;
var phoneRegNoArea = /^[1-9]{1}[0-9]{5,8}$/;
var prompt = "您输入的电话号码不正确!"
if( strPhone.length > 9 ) {
if( phoneRegWithArea.test(strPhone) ){
return true;
}else{
alert( prompt );
return false;
}
}else{
if( phoneRegNoArea.test( strPhone ) ){
return true;
}else{
alert( prompt );
return false;
}
}
}
/*
用途:检查复选框被选中的数目
输入:
checkboxID:字符串
返回:
返回该复选框中被选中的数目
*/
function checkSelect( checkboxID ) {
var check = 0;
var i=0;
if( document.all(checkboxID).length > 0 ) {
for( i=0; i<document.all(checkboxID).length; i++ ) {
if( document.all(checkboxID).item( i ).checked ) {
check += 1;
}
}
}else{
if( document.all(checkboxID).checked )
check = 1;
}
return check;
}
function getTotalBytes(varField) {
if(varField == null)
return -1;
var totalCount = 0;
for (i = 0; i< varField.value.length; i++) {
if (varField.value.charCodeAt(i) > 127)
totalCount += 2;
else
totalCount++ ;
}
return totalCount;
}
function getFirstSelectedValue( checkboxID ){
var value = null;
var i=0;
if( document.all(checkboxID).length > 0 ){
for( i=0; i<document.all(checkboxID).length; i++ ){
if( document.all(checkboxID).item( i ).checked ){
value = document.all(checkboxID).item(i).value;
break;
}
}
} else {
if( document.all(checkboxID).checked )
value = document.all(checkboxID).value;
}
return value;
}
function getFirstSelectedIndex( checkboxID ){
var value = -2;
var i=0;
if( document.all(checkboxID).length > 0 ){
for( i=0; i<document.all(checkboxID).length; i++ ) {
if( document.all(checkboxID).item( i ).checked ) {
value = i;
break;
}
}
} else {
if( document.all(checkboxID).checked )
value = -1;
}
return value;
}
function selectAll( checkboxID,status ){
if( document.all(checkboxID) == null)
return;
if( document.all(checkboxID).length > 0 ){
for( i=0; i<document.all(checkboxID).length; i++ ){
document.all(checkboxID).item( i ).checked = status;
}
} else {
document.all(checkboxID).checked = status;
}
}
function selectInverse( checkboxID ) {
if( document.all(checkboxID) == null)
return;
if( document.all(checkboxID).length > 0 ) {
for( i=0; i<document.all(checkboxID).length; i++ ) {
document.all(checkboxID).item( i ).checked = !document.all(checkboxID).item( i ).checked;
}
} else {
document.all(checkboxID).checked = !document.all(checkboxID).checked;
}
}
function checkDate( value ) {
if(value=='') return true;
if(value.length!=8 || !isNumber(value)) return false;
var year = value.substring(0,4);
if(year>"2100" || year< "1900")
return false;
var month = value.substring(4,6);
if(month>"12" || month< "01") return false;
var day = value.substring(6,8);
if(day>getMaxDay(year,month) || day< "01") return false;
return true;
}
/*
用途:检查输入的起止日期是否正确,规则为两个日期的格式正确或都为空
且结束日期>=起始日期
输入:
startDate:起始日期,字符串
endDate: 结束日期,字符串
返回:
如果通过验证返回true,否则返回false
*/
function checkPeriod( startDate,endDate ) {
if( !checkDate(startDate) ) {
alert("起始日期不正确!");
return false;
} else if( !checkDate(endDate) ) {
alert("终止日期不正确!");
return false;
} else if( startDate > endDate ) {
alert("起始日期不能大于终止日期!");
return false;
}
return true;
}
/*
用途:检查证券代码是否正确
输入:
secCode:证券代码
返回:
如果通过验证返回true,否则返回false
*/
function checkSecCode( secCode ) {
if( secCode.length !=6 ){
alert("证券代码长度应该为6位");
return false;
}
if(!isNumber( secCode ) ){
alert("证券代码只能包含数字");
return false;
}
return true;
}
/****************************************************
function:cTrim(sInputString,iType)
description:字符串去空格的函数
parameters:iType:1=去掉字符串左边的空格
2=去掉字符串左边的空格
0=去掉字符串左边和右边的空格
return value:去掉空格的字符串
****************************************************/
function cTrim(sInputString,iType)
{
var sTmpStr = ' ';
var i = -1;
if(iType == 0 || iType == 1)
{
while(sTmpStr == ' ')
{
++i;
sTmpStr = sInputString.substr(i,1);
}
sInputString = sInputString.substring(i);
}
if(iType == 0 || iType == 2)
{
sTmpStr = ' ';
i = sInputString.length;
while(sTmpStr == ' ')
{
--i;
sTmpStr = sInputString.substr(i,1);
}
sInputString = sInputString.substring(0,i+1);
}
return sInputString;
}
/*
-------------------------------------------------------------------------------
说明:JavaScript脚本,验证表单中的数据项 begin
-------------------------------------------------------------------------------
*/
function checkForm(objFrm){
var len = 0;
len = objFrm.elements.length;
var i = 0;
var objCheck;
//文本框
for(i = 0; i < len; i ++){
objCheck = objFrm.elements[i];
if(objCheck.type =="text" && !f_checkTextValid(objCheck) ){
return false;
}
}
//下拉框
for(i = 0; i < len; i ++){
objCheck = objFrm.elements[i];
if(objCheck.type =="select-one" && !f_checkSelectValid(objCheck) ){
return false;
}
}
//时间段有效
if( f_checkStartAndEndDate(objFrm) == false) return false;
return true;
}
function f_checkSelectValid(obj){
//alert("check select");
if(obj.options.length <= 0){
alert("下拉选框无数据!");
return false;
}
return true;
}
function f_checkStartAndEndDate(frm){
var len = frm.elements.length;
if(len == null && len == 0) return true;
var i=0;
var temp;
var objCheck;
var objStartDate;
var objEndDate;
//alert("start date period check");
try{
for(i=0; i< len ; i++){
objCheck = frm.elements[i];
temp = objCheck.name;
if( temp.indexOf("startDate") >0 ||temp.indexOf("beginDate")>0 )
objStartDate = objCheck;
if( temp.indexOf("endDate") > 0 )
objEndDate = objCheck;
}
//alert(objStartDate.value);
//alert(objEndDate.value);
if(objStartDate.value==null || objStartDate.value =="" || objStartDate.value ==null || objStartDate.value ==""){
return true;
}
return checkTwoDate(objStartDate.value, objEndDate.value);
//alert("end date period check");
}catch(E){}
return true;
}
function f_checkTextValid(obj){
//不能为空
if(obj.getAttribute("isNeed") != null){
if(f_isNotNull(obj) == false) return false;
}
//不能超过长度
if(obj.getAttribute("maxlength") != null){
if(f_checkLength(obj) == false) return false;
}
var checkType ="";
checkType = obj.getAttribute("checkType");
if(checkType==null||checkType=="") return true;
//
if (checkType.indexOf("number") >=0){
if(f_isNumber(obj) == false) return false;
if(f_checkNumType(obj,checkType) == false) return false;
}
//
if (checkType.indexOf("positive") >=0){
if(f_isNumber(obj) == false) return false;
if(f_isPositive(obj)==false) return false;
if(f_checkNumType(obj,checkType) == false) return false;
}
if (checkType.indexOf("date") >=0){
if(f_checkDate(obj) == false) return false;
}
/*
switch(checkType){
case "number": if(f_isNumber(obj) == false) return false;break;
case "date": if(f_checkDate(obj) == false) return false;break;
default:
}
*/
return true;
}
function f_isNotNull(obj){
if(obj.value == ""){
f_alert(obj, " 不允许为空值!");
return false;
}
return true;
}
function f_isNumber(obj){
if(isNaN(obj.value)){
f_alert(obj," 应为数值类型");
return false;
}
return true;
}
function f_checkDate(obj) {
if(checkDate(obj.value) ==false){
f_alert(obj," 不是合法日期格式!");
return false;
}
return true;
}
function f_checkLength(obj){
if(getTotalBytes(obj) > Math.abs( obj.getAttribute("maxlength") ) ){
f_alert(obj," 超出长度限制!");
return false;
}
return true;
}
function f_alert(obj,alertStr){
var fielName = obj.getAttribute("fieldName");
if(fielName == null)
fielName = "";
alert(fielName + "/n" +alertStr);
obj.select();
obj.focus();
}
function f_checkNumType(obj, numType){
//假设: 已经进行数字类型判断
var strTemp;
var numpric;
var numLen;
var strArr;
var defaultLen = 19;
var defaultpric = 5;
try{
if(numType == null|| numType =="") return f_checkNumLenPrec(obj,defaultLen, defaultpric);
if(numType.indexOf("(") < 0 || numType.indexOf(")") < 0 ) return f_checkNumLenPrec(obj,defaultLen, defaultpric);
strTemp = numType.substr( numType.indexOf("(") + 1 ,numType.indexOf(")") - numType.indexOf("(") -1 );
if(strTemp == null||strTemp =="") return f_checkNumLenPrec(obj,defaultLen, defaultpric);
strArr = strTemp.split(",");
numLen = Math.abs( strArr[0] );
numpric = Math.abs( strArr[1] );
return f_checkNumLenPrec(obj,numLen, numpric);
}catch(e){
alert("in f_checkNumType = " + e);
return f_checkNumLenPrec(obj,defaultLen, defaultpric);
}
}
function f_checkNumLenPrec(obj, len, pric){
var numReg;
var value = obj.value;
var strValueTemp, strInt, strDec;
//alert(value + "=====" + len + "====="+ pric);
try{
numReg =/[/-]/;
strValueTemp = value.replace(numReg, "");
strValueTemp = strValueTemp.replace(numReg, "");
//整数
if(pric==0){
numReg =/[/.]/;
//alert(numReg.test(value));
if(numReg.test(value) == true){
f_alert(obj, "输入必须为整数类型!");
return false;
}
}
if(strValueTemp.indexOf(".") < 0 ){
//alert("lennth==" + strValueTemp);
if(strValueTemp.length >( len - pric)){
f_alert(obj, "整数位不能超过"+ (len - pric) +"位");
return false;
}
}else{
strInt = strValueTemp.substr( 0, strValueTemp.indexOf(".") );
//alert("lennth==" + strInt);
if(strInt.length >( len - pric)){
f_alert(obj, "整数位不能超过"+ (len - pric) +"位");
return false;
}
strDec = strValueTemp.substr( (strValueTemp.indexOf(".")+1), strValueTemp.length );
//alert("pric==" + strDec);
if(strDec.length > pric){
f_alert(obj, "小数位不能超过"+ pric +"位");
return false;
}
}
return true;
}catch(e){
alert("in f_checkNumLenPrec = " + e);
return false;
}
}
function f_isPositive(obj){
var numReg =/[/-]/;
if(numReg.test(obj.value) == true){
f_alert(obj, "必须为正数!");
return false;
}
return true;
}
/*
function selectedCheckboxCount(form)
功能说明:对Form中选中的可选项计数
参数说明:
form:指定的表单
*/
function selectedCheckboxCount(form){
var length =0;
var i=0;
var count =0;
eles = form.elements;
while(i<eles.length){
obj= eles.item(i);
//type = obj.attributes.item("type").nodeValue;
type = obj.type;
if(type == "checkbox"){
if(obj.checked){
count++;
}
}
i++;
}
return count;
}
//得到字节长度
function getByteLen(str)
{
var l = str.length;
var n = l;
for ( var i=0; i<l; i++ )
if ( str.charCodeAt(i) <0 || str.charCodeAt(i) >255 )
n=n+1;
return n
}
/*
说明:
1.清除表格中的数据(0.0 和 0)
2.如果cell中没有数据,则自动加上一个空格
3.清除空白行的checkbox
参数:
clearzero:是否清除"0"、"0.0",false不清除、true清除(默认为true)
tablename:要清除的表格名字,默认为sortTable
*/
function clear_table(clearzero,tablename)
{
var tobject;
if(tablename==null)
tobject=gmobj("sortTable");
else
tobject=gmobj(tablename);
//如果table未定义,则不进行过滤
if(tobject==null)
return;
//如果函数调用参数为空,表示要清除0、0.0;反之,不要清除0、0.0。
var clear = (clearzero==null)?true:clearzero;
//清除0、0.0,填补空格
var rows = tobject.rows;
var j=0;
for(var i=0;i<rows.length;i++)
{
//取得第一个cell的属性clear,如果为1,表示该行没有数据,则清除该行所有数据
while(tobject.rows[i].cells[j] != null)
{
if(clear)
{
if(tobject.rows[i].cells[j].innerHTML==0 ||tobject.rows[i].cells[j].innerHTML==0.0||tobject.rows[i].cells[j].innerHTML=="")
tobject.rows[i].cells[j].innerText=" ";
}
else
{
if (tobject.rows[i].cells[j].innerHTML=="")
tobject.rows[i].cells[j].innerText=" ";
}
j++;
}
j=0;
}
return true;
}
function gmobj(mtxt) /* Get object by object name */
{
if (document.getElementById) {
m=document.getElementById(mtxt);
} else if (document.all) {
m=document.all[mtxt];
} else if (document.layers) {
m=document.layers[mtxt];
}
return m;
}
/*
-------------------------------------------------------------------------------
说明:JavaScript脚本,验证表单中的数据项 end
-------------------------------------------------------------------------------
*/
/*
用途:检查输入字符串是否是带小数的数字格式,可以是负数(并且满足规定的精度)
输入:str:字符串
l:总位数
d:小数点后位数
返回:
如果通过验证返回true,否则返回false
*/
function isDecimal( str,l,d ){
if(isInteger(str)) {
if (l==null) return true;
if (str<0) l--;
if (str.length<=l) return true;
}
var re = /^[-]{0,1}(/d+)[/.]+(/d+)$/;
if (re.test(str)) {
if (l==null) return true;
if (d==null) d=0;
if(RegExp.$1==0&&RegExp.$2==0) return false;
if (RegExp.$1.length+RegExp.$2.length<=l
&& RegExp.$2.length<=d) return true;
}
return false;
}
οnclick="isNull('Co.PageForm.CompetitorName');"
附:
B.1 北美电话号码
North American Numbering Plan(北美编号方案)对北美地区的电话号码格式做出了定义。根据这一方案,北美地区(美国、加拿大、加勒比海地区大部以及其他几个地区)的电话号码由一个3位数的区号和一个7位数的号码构成(这7位数字又分成一个 3位数的局号和一个4位数的线路号,局号和线路号之间用连字符分隔)。每位电话号码可以是任意数字,但区号和局号的第一位数字不能是0或1。在书写电话号码的时候,人们往往把区号放在括号里,而且还往往会在区号与实际电话号码之间加上一个连字符来分隔它们。匹配(555) 555-5555(右括号的后面有一个空格)或(555)555-5555或555-555-5555其中之一很简单,但要想编写一个能够同时匹配这些电话号码的模式就不那么容易了。
这个模式的开头是样子很怪的/(?,它负责匹配用来括住区号的括号——这对括号是可选的:/(匹配(字符,?表示匹配(的零次或一次出现。接下来的[2-9]/d/d负责匹配一个3位数的区号(第1位数字只能是2到9)。/)?匹配一个可选的右括号,[ -]?匹配一个空格或连字符——这个字符也是可选的。[2-9]/d/d-/d{4}匹配电话号码的剩余部分:一个3位数的局号(第1位数字只能是2到9)、一个连字符和最后4位数字。
只须稍做修改,这个模式就可以用来匹配北美电话号码的其他格式。比如像555.555.5555这样的号码。
这个模式的开头部分使用了字符集合[/(.]?来匹配一个(或.字符——它们都是可选的。类似地,[/).]?匹配一个)或.字符——它们也都是可选的;[-.]匹配一个-或.字符。只要把这两个例子看明白了,你就可以轻而易举地把其他电话号码格式也添加到你的模式里。
B.2 美国邮政编码
美国于1963年开始使用邮政编码(简称ZIP编码,ZIP是Zone Improvement Plan的首字母缩写)。美国目前有40 000多个ZIP编码,它们全都由数字构成(第1位数字代表从美国东部到西部的一个地域,0代表东海岸地区,9代表西海岸地区)。在1983年,美国邮政总局开始使用扩展的ZIP编码,简称ZIP+4编码。新增加的4位数字对信件投送区域做了更细致的划分(细化到某个特定的城市街区或某幢特定的建筑物),这大大提高了信件的投送效率和准确性。不过,ZIP+4编码的使用是可选的,所以对ZIP编码进行检查通常必须同时照顾到5位数字的ZIP编码和9位数字的ZIP+4编码(ZIP+4编码中的后4位数字与前5位数字之间要用一个连字符隔开)。
/d{5}匹配任意5位数字,(-/d{4})?匹配一个连字符和后4位数字。因为后4位数字是可选的,所以要把-/d{4}用括号括起来(这使它成为了一个子表达式),再用一个?来表明这个子表达式最多只允许出现一次。
B.3 加拿大邮政编码
加拿大邮政编码由6个交替出现的字母和数字字符构成。每个编码分成两部分:前3个字符用来给出FSA代码(forward sortation area,地区代码),后3个字符用来给出LDU代码(local delivery unit,街道代码)。FSA代码的第一个字符用来表明省、市或地区(这个字符有18种合法的选择;比如A代表纽芬兰地区;B代表新斯科舍地区;K、L、N和P代表安大略省;M代表多伦多市,等等),而我们的模式应该确保这第一个字符是合法的。在写出一个加拿大邮政编码的时候,FSA代码和LDU代码之间通常要用一个空格隔开。
[ABCEGHJKLMNPRSTVXY]匹配那18个合法字符中的任何一个,/d[A-Z]匹配一个数字和一个紧随其后的任意字母;它们合起来将匹配一个合法的FSA代码。/d[A-Z]/d匹配LDU代码,任意两个数字字符夹着任意一个字母。
| 注意 加拿大邮政编码不要求必须以大写形式写出,所以在使用上面这个正则表达式进行匹配时一般用不着区分字母的大小写。 |
B.4 英国邮政编码
英国邮政编码由5个、6个或7个字符构成,这些编码是由英国皇家邮政局定义的。英国邮政编码由两部分构成:代表邮政区划的外码(outcode)和代表城市街道的内码(incode)。外码是一个或两个字母后面跟着一位或两位数字,或者是一个或两个字母后面跟着一个数字和一个字母。内码永远是一位数字后面跟着两个字母(除C、I、K、O和V以外的任意字母——合法的英国邮政编码是不会在它的内码部分使用这5个字母的)。内码和外码之间要用一个空格隔开。
在这个模式里,[A-Z]{1, 2}/d匹配一个或两个字母紧跟着一位数字,随后的[A-Z/d]?匹配一个可选的字母或数字字符。于是,[A-Z]{1, 2}/d[A-Z/d]?将匹配任何一种合法的外码组合。内码部分由/d[ABD-HJLNP-UW-Z]{2}负责匹配,它将匹配任意一位数字和紧随其后的两个允许用在内码里的字母(A、B、D到H、J、L、N、P到U、W到Z)。
| 注意 英国邮政编码不要求必须以大写形式写出,所以在使用上面这个正则表达式进行匹配时一般用不着区分字母的大小写。 |
B.5 美国社会安全号码
美国的社会安全号码(social security number,简称SSN号码)由3组以连字符隔开的数字构成:第1组包含着3位数字,第2组包含着2位数字,第3组包含着4位数字。从1972年起,美国政府开始根据SSN号码申请人提供的住址来分配第一组里的3位数字。
/d{3}-/d{2}-/d{4}将依次匹配:任意3位数字、一个连字符、任意2位数字、一个连字符、任意4位数字。
| 注意 从理论上讲,SSN号码可以是任意数字组合,但从现实看,它们必须满足以下几项要求。首先,在一个合法的SSN号码里不可能出现全零字段;其次,第1组数字(到目前为止)不得大于728(因为SSN号码迄今为止还没用过那么大的数字,但未来可能会用到)。不过,一个能满足上述要求的模式会十分的复杂,因而比较简单的/d{3}-/d{2}-/d{4}更常见一些。 |
B.6 IP地址
IP地址由4个字节构成(这4个字节的取值范围都是0~255)。IP地址通常被写成4组以.字符隔开的整数(每个整数由1~3位数字构成)。
这个模式使用了一系列嵌套子表达式。我们先来说说由4个子表达式构成的(((/d{1, 2})|(1/d{2})|(2[0-4]/d)|(25[0-5])/.):(/d{1, 2})匹配任意一位或两位数字(0~99);(1/d{2})匹配以1开头的任意三位数字(100~199);(2[0-4]/d)匹配整数200~249;(25[0-5])匹配整数250~255。这几个子表达式通过|操作符结合为一个更大的子表达式(其含义是只须匹配这4个子表达式之一即可)。随后的/ .用来匹配.字符,它与前4个子表达式构成的子表达式又构成了一个更大的子表达式,而接下来的{3}表明需要重复3次。最后,数值范围又重复了一次(这次省略了尾部的/ .)以匹配IP地址里的最后一组数字。通过把4组以.分隔的数字的取值范围都限制在0~255之间,这个模式准确无误地做到了只匹配合法的IP地址,但不匹配非法的IP地址。
| 注意 第7章对这个IP地址的例子做了详细的解释。 |
B.7 URL地址
对URL地址进行匹配是一个有着相当难度的任务——其复杂性取决于你想获得多么精确的匹配结果。在最简单的情况下,你的URL匹配模式至少应该匹配到以下内容:协议名(http或https)、一个主机名、一个可选的端口号、一个文件路径。
https?://匹配http://或https://(?使得字符s是可选的)。[-/w.]+匹配主机名。(:/d+)?匹配一个可选的端口号(参见上例中的第2和第6行)。(/([/w/_.]*)?)?负责匹配一个文件路径:外层的子表达式匹配一个可选的/字符,内层的子表达式匹配那个文件路径本身。正如大家看到的那样,这个模式不能正确处理查询字符串,也不能正确解读嵌在URL地址里的“username:password(用户名:口令字)”。不过,对绝大多数URL地址而言,这个模式的使用效果(匹配到主机名、端口号和文件路径)还是令人满意的。
| 注意 URL地址不要求必须以大写形式写出,所以在使用上面这个正则表达式进行匹配时一般用不着区分字母的大小写。 |
| 提示 如果你还想匹配使用了ftp协议的URL地址,把https?://替换为(http|https|ftp)即可。使用了其他协议的URL地址也可以按照类似的思路来匹配。 |
B.8 完整的URL地址
下面是一个更完备(也更慢)的URL地址匹配模式,它还可以匹配URL查询字符串(嵌在URL地址里的变量信息,这些信息与URL地址中的网址部分要用一个?隔开)以及可选的用户登录信息。
这个模式是在前一个例子的基础上改进而来的。这次紧跟在https?://后面的是(/w*:/w*@)?,它将匹配嵌在URL字符串里的用户名和口令字(用户名和口令字要用:隔开,它们的后面还跟着一个@字符),参见这个例子里的第4行。另外,这次在路径信息的后面还多了一个子表达式(/?/S+)?,它负责匹配查询字符串。查询字符串是在URL字符串里出现在?后面的文本,这些文本是可选的,所以这个子表达式的后面还紧跟着一个?。
| 注意 URL地址不要求必须以大写形式给出,所以在使用上面这个正则表达式进行匹配时一般用不着区分字母的大小写。 |
| 提示 能不能总是使用这个更完备的模式来取代前一个呢?从理论上讲,这没有什么不妥,但在实际工作中,因为这个模式比较复杂、处理速度也比较慢,所以如果没有特殊的必要,还是不使用它比较好。 |
B.9 电子邮件地址
用一个正则表达式来匹配电子邮件地址是一项很常见的任务。一般来说,如果需要匹配的电子邮件地址比较简单,相应的正则表达式就不会很复杂。
(/w+/ .)*/w+负责匹配电子邮件地址里的用户名部分(@之前的所有文本):(/w+/ .)*匹配一些由.结束的文本的零次或多次重复出现,/w+匹配必不可少的文本(这个组合将匹配ben和ben.forta,等等)。接下来,@匹配@字符本身,(/w+/ .)匹配至少一个以.结束的字符串,[A-Za-z]+匹配顶级域名(com、edu、us或uk,等等)。
合法的电子邮件地址必须在排版格式方面同时满足许多项规定。这个模式不能用来匹配每一种可能的电子邮件地址。比如说,这个模式会认为ben..forta@forta.com是一个合法匹配(但这显然不是一个合法的电子邮件地址),它不能用来匹配以IP地址做为主机名的电子邮件地址(但这种电子邮件地址是合法的)。不过,因为绝大多数电子邮件地址都能与这个模式相匹配,所以你不妨先用它试试,如果效果不佳再考虑对之进行改进。
| 注意 电子邮件地址不要求必须以大写形式写出,所以在使用上面这个正则表达式进行匹配时一般用不着区分字母的大小写。 |
B.10 HTML注释
HTML页面里的注释必须被放在<!--和-->标签之间(这两个标签必须至少包含两个连字符,多于两个没有关系)。在浏览(或调试)Web页面的时候,我们往往需要把所有的注释都找出来。
<!-{2, }匹配HTML注释的开始标签,也就是<!后面紧跟着两个或更多个连字符的情况。.*?匹配HTML注释的文字部分(注意,这里用的是一个懒惰型元字符)。-{2, }>匹配HTML注释的结束标签。
| 注意 这个模式匹配两个或更多个连字符,所以还可以用来查找CFML注释(这种注释的开始/结束标签里包含着3个连字符)。不过,这个模式没有对HTML注释的开始标签和结束标签所包含的连字符的个数是否配对进行检查(那可以用来检查HTML注释的格式是否有误)。 |
B.11 JavaScript注释
JavaScript(其他脚本语言如ActionScript和ECMA Script的其他变体等)代码里的注释都以//开头。正如刚才那个HTML注释的例子所示,把某给定页面里的所有注释全部查找出来是很有用的。
这是一个很简单的模式://.*匹配//和紧随其后的注释内容。
| 注意 与绝大多数正则表达式实现不同,在ColdFusion里,总是匹配换行符。因此,如果你正在使用的是ColdFusion,你将需要把这个模式修改成使用懒惰型元字符的样子,把.*替换为.*?。 |
B.12 信用卡号码
信用卡号码本身是否合法不能用正则表达式来检查,最终的结论要由信用卡的发行机构做出。我们这里说的检查是指使用正则表达式来检查信用卡号码的格式是否符合有关规定,其主要目的是为了——在对信用卡号码做进一步处理之前——把有打字错误的信用卡号码(比如多输入一位数字或少输入一位数字等情况)排除在外。
| 注意 这里使用的模式都有这样一个前提假设:信用卡号码里的空格和连字符已提前被去掉。一般来说,在使用正则表达式对信用卡号码进行匹配处理之前,先把其中的非数字字符去掉会给匹配操作带来很多便利;但这只是经验之谈,你应该根据具体情况来掌握。 |
所有的信用卡都遵守着同一种基本的编码模式——以特定的数字序列开头,号码的总位数是一个固定的值。我们先来看看MasterCard卡的情况。
MasterCard卡的号码总长度是16位数字;第1位数字永远是5,第2位数字是1到5之一。5[1-5]匹配前两位数字;{14}匹配随后的14位数字。
Visa卡的情况稍微复杂一些。
Visa卡的第1位号码永远是4,总长度是13或16位数字(不包括14或15,所以这里不能使用一个数字区间)。4匹配字符4本身,/d{12}匹配接下来的12位数字,(/d{3})?匹配可选的最后3位数字。
用来匹配美国运通卡号的模式相对要简单得多。
美国运通卡的号码总长度是15位,前两位号码必须是34或37。3[47]匹配前两位数字,/d{13}匹配剩余的13位数字。
用来匹配Discover卡号的模式也很简单。
Discover卡的号码总长度是16位,前4位号码必须是6011。6011/d {14}解决了问题。
Diners Club卡的情况稍微复杂一些。
Diners Club卡的号码总长度是14位,必须以300到305、36或38开头。如果前三位号码是300到305,后面必须再有11位数字;如果前两位号码是36或38,则后面必须再有12位数字。我们这里采用了一个比较简单的办法:先匹配前3位数字——(30[0-5]|36/d|38/d)包含3个子表达式,只要其中之一得到匹配即可;其中30[0-5]匹配300~305,36/d匹配以36开头的任意3位数,38/d匹配以38开头的任意3位数。最后,/d{11}匹配剩余的11位数字。
现在,只要把上述5种信用卡号码的匹配模式组合成一个更大的模式就可以全面解决这个问题了:
这个模式用|操作符(正则表达式语言中的逻辑或操作符)把前面得到的5个模式结合到了一起。有了它,我们就可以一次完成对5种常见信用卡的号码格式进行检查了。
| 注意 这里使用的模式只能检查信用卡的号码是不是以正确的数字序列开头和是不是有着正确的总长度。不过,并非所有以4开头的13位数字都是合法的Visa卡号——信用卡号码还必须满足一个名为Mod 10的数学算法(这个算法适用于所有的信用卡类型)。在对信用卡进行编程处理的时候,Mod 10算法是一个必不可少的重要环节,但这项检查不属于正则表达式的工作——因为正则表达式不涉及数学运算。 |
B.13 小结
在本附录里,你看到了我们在前面的章程里介绍的许多概念和思路在实际工作中的应用例子。根据你遇到的具体问题,这些例子里的模式或者可以直接拿过来使用,或者需要稍做改动。我们把这些模式作为欢迎大家进入正则表达式世界的礼物,希望它们能帮助你拓展思路并在此基础上构造出更精彩更实用的模式来。