精通正则表达式(JavaScript)
在上一篇精通正则表达式(正则引擎)中大概的讲解了一下正则引擎的相关知识,了解了它的匹配原理,接下来我们在js这门语言里面来详细的使用一下。
在js中常用于字符串处理、表单验证、处理DOM模型、纯编程逻辑等。js中的正则表达式使用方式提供了两种:普通方式;构造函数方式。
普通方式
普通方式:var reg=/表达式/附加参数
表达式:一个字符串,代表了某种规则,其中可以使用某些特殊字符来代表特殊的规则。
附加参数:用来扩展表达式的含义,目前主要有三个参数:
g:代表可以进行全局匹配。
i:代表不区分大小写匹配。
m:代表可以进行多行匹配。
上面三个参数可以任意组合,代表符合含义,当然也可以不加参数。
例如:
var reg1=/[0-9]*b/;
var reg2=/[a-z]+f/g;
var reg3=/^[a-z]/i;
var reg4=/^[a-z]/gm;
构造函数方式
构造函数方式:var reg=new RegExp(“表达式”,”附加参数”);
其中的表达式和附加参数和普通方式一样。
例如:var reg1=new RegExp(“a|b”);
var reg2=new RegExp(“[a-z]$”,”i”);
普通方式的的表达式必须是一个常量字符串,而构造函数中的表达式可以是常量字符串,也可以是一个js变量,例如:
var value=“abc”;
var reg=new RegExp(value,”i”);
如下为js的其他部分元字符:
1、表达式操作
1.1exec
exec(str),返回str中与表达式相匹配的第一个字符串,而且以数组的形式表现,当然如果表达式中含有捕捉用的小括号,则返回的数组中也可能含有()中的匹配字符串,例如:
var regx=/\d+/;
var rs=regx.exec(“3432ddf53”);
返回的rs值为:{3432}
var regx2=new RegExp(“ab(\\d+)c”);
var rs2=regx2.exec(“ab234c44”);
返回的rs值为:{ab234c,234}
另外,如果有多个合适的匹配,则第一次执行exec返回一个第一个匹配,此时继续执行exec,则依次返回第二个第三个匹配。例如:
var regx=/user\d/g;
var rs=regx.exec(“ddduser1dsfuser2dd”);
var rs1=regx.exec(“ddduser1dsfuser2dd”);
则rs的值为{user1},rs的值为{user2},当然注意regx中的g参数是必须的,否则无论exec执行多少次,都返回第一个匹配
1.2test
test(str),判断字符串str是否匹配表达式,返回一个布尔值。例如:
var regx=/user\d+/g;
var flag=regx.test(“user12dd”);
flag的值为true。
var reg=/user\d+/g; var result1=reg.test("uuser12f"); var result2=reg.test("user"); document.write(result1+" "+result2);
1.3match
match(expr),返回与expr相匹配的一个字符串数组,如果没有加参数g,则返回第一个匹配,加入参数g则返回所有的匹配 例子:
var regx=/user\d/g;
var str=“user13userddduser345”;
var rs=str.match(regx);
rs的值为:{user1,user3}
var reg1=/user\d+/; var reg2=/user\d+/g; var str="user12uerdduser33"; var result1=str.match(reg1); var result2=str.match(reg2); document.write(result1+" "+result2);
1.4search
search(expr),返回字符串中与expr相匹配的第一个匹配的index值。 例子:
var regx=/user\d/g;
var str=“user13userddduser345”; var rs=str.search(regx);
rs的值为:0
var reg1=/user\d+/g; var str="yyuser12uerdduser33"; var result1=str.search(reg1); document.write(result1);
1.5replace
replace(expr,str),将字符串中匹配expr的部分替换为str。另外在replace方法中,str中可以含有一种变量符号$,格式为$n,代表匹配中被记住的第n的匹配字符串(注意小括号可以记忆匹配)。 例子1:
var regx=/user\d/g;
var str=“user13userddduser345”;
var rs=str.replace(regx,”00”);
rs的值为:003userddd0045
例子2:
var regx=/u(se)r\d/g;
var str=“user13userddduser345”; var rs=str.replace(regx,”$1”);
rs的值为:se3userdddse45
对于replace(expr,str)方法还要特别注意一点,如果expr是一个表达式对象则会进行全局替换(此时表达式必须附加参数g,否则也只是替换第一个匹配),如果expr是一个字符串对象,则只会替换第一个匹配的部分,例如:
var regx=“user”;
var str=“user13userddduser345”;
var rs=str.replace(regx,”00”);
rs的值为: 0013userddduser345
var reg=/(user)\d+/g; var str="yyuser12uerdduser33"; var result=str.replace(reg,"$1"+"007"); document.write(result);
对于replace(expr,str)的方法还有一点比较重要,这里的str可以使字符串,也可以是一个函数。我们先来看一个例子:
function init() { var reg=/(use)(r)\d+/g; var str="yyuser12uerdduser33"; var result=str.replace(reg,replaceFunction); document.write(result); } function replaceFunction() { var args=arguments; return args[0]; }
你可以调试一下,发现里面的arguments这个维数组(严格意义上来说不是数组)如下图:
第一个元素是我们匹配成功的字符串,倒数第一个是我们需要匹配的完整的字符串,倒数第二个表示此次匹配成功的位置(一个字符串的第0个位置是第一个字母的前面,第1个位置是第1个字母和第2个字母之间,一次类推),中间的数量会右边变,代表你的正则表达式里面记录的数据,也就是括号()里面的信息,我这里有(use)和(r),所以刚好对应。
其实参数为函数的时候就是代表正则引擎将匹配的部分过程开放出来了,让我们可以控制一部分操作,这个方法的目的是捕获引擎匹配成功时的状态,然后把所有数据通过arguments开放出来,并且有用户自己定义是否需要将这些匹配成功的数据替换成为别的,我的代码里面return的是第一个元素,也就是本身,所以最后结果不会改变,而且由于我的表达式使用了g(全局匹配),所以你会发现还会第二次进入这个函数,第二次匹配的就是user33。由此我们发现了参数为函数时的强大功能,我们可以捕获引擎匹配成功的每一个状态,并且可以将这些匹配成功的信息修改为我们自己想要的。相比传递字符串参数来的更灵活。方法自己的参数你也可以自己设置,稍微熟悉js语法的朋友都知道,你的function有几个参数,肯定是一次对应arguments里面的数据的,再次就不多讲了。
1.6split
split(expr),将字符串以匹配expr的部分做分割,返回一个数组,而且表达式是否附加参数g都没有关系,结果是一样的。 例子:
var regx=/user\d/g;
var str=“user13userddduser345”;
var rs=str.split(regx);
rs的值为:{3userddd,45}
var reg=/user\d/g; var str="yyuser12uerdduser33"; var result=str.split(reg); document.write(result);
2、表达式相关属性
2.1lastIndex
lastIndex,返回开始下一个匹配的位置,注意必须是全局匹配(表达式中带有g参数)时,lastIndex才会有不断返回下一个匹配值,否则该值为总是返回第一个下一个匹配位置,例如: var regx=/user\d/;
var rs=regx.exec(“sdsfuser1dfsfuser2”);
var lastIndex1=regx.lastIndex; rs=regx.exec(“sdsfuser1dfsfuser2”);
var lastIndex2=regx.lastIndex; rs=regx.exec(“sdsfuser1dfsfuser2”);
var lastIndex3=regx.lastIndex;
上面lastIndex1为0,第二个lastIndex2也为0,第三个也是0;如果regx=/user\d/g,则第一个为9,第二个为18,第三个为0。
var regx=/user\d/g; var rs=regx.exec("sdsfuser1dfsfuser2"); var lastIndex1=regx.lastIndex; rs=regx.exec("sdsfuser1dfsfuser2"); var lastIndex2=regx.lastIndex; rs=regx.exec("sdsfuser1dfsfuser2"); var lastIndex3=regx.lastIndex; document.write(lastIndex1+" "+lastIndex2+" "+lastIndex3);
2.2source
source,返回表达式字符串自身。例如:
var regx=/user\d/;
var rs=regx.exec(“sdsfuser1dfsfuser2”);
var source=regx.source;
source的值为user\d
2.3index
index,返回当前匹配的位置。例如:
var regx=/user\d/;
var rs=regx.exec(“sdsfuser1dfsfuser2”);
var index1=rs.index; rs=regx.exec(“sdsfuser1dfsfuser2”);
var index2=rs.index;
rs=regx.exec(“sdsfuser1dfsfuser2”);
var index3=rs.index;
index1为4,index2为4,index3为4,如果表达式加入参数g,则index1为4,index2为13,index3会报错(index为空或不是对象)。
2.4input
input,用于匹配的字符串。例如:
var regx=/user\d/;
var rs=regx.exec(“sdsfuser1dfsfuser2”);
var input=rs.input;
input的值为sdsfuser1dfsfuser2。
2.5[0]
[0],返回匹配结果中的第一个匹配值,对于match而言可能返回一个多值的数字,则除了[0]外,还可以取[1]、[2]等等。例如:
var regx=/user\d/g;
var rs=regx.exec(“sdsfuser1dfsfuser2”); var value1=rs[0]; rs=regx.exec(“sdsfuser1dfsfuser2”);
var value2=rs[0];
value1的值为user1,value2的值为user2
3实战
3.1
请将下面的字符串转换为对应的字符串:(我们公司一个面试题)
t0.supermap.com/tiles/4/3/2.png
t4.supermap.com/tiles/m4/4/3.jpg
a7.supermap.com/tiles/5/m4/6.png
转换为对应的
m0.iclient.com/tiles.png?x=4&y=3&z=2
m4.iclient.com/tiles.jpg?x=m4&y=4&z=3
m7.iclient.com/tiles.png?x=5&y=m4&z=6
答案(不止一个,这只是其中一个):
var regx=/^[a-z]([0-9]\.)supermap(\.com\/tiles)\/([a-z0-9]+)\/([a-z0-9]+)\/([a-z0-9]+)\.(png|jpg)$/; var str1="t0.supermap.com/tiles/4/3/2.png"; var str2="t4.supermap.com/tiles/m4/4/3.jpg"; var str3="a7.supermap.com/tiles/5/m4/6.png"; var str="m"+"$1"+"iclient"+"$2"+"."+"$6"+"?x="+"$3"+"&y="+"$4"+"&z="+"$5"; var result1=str1.replace(regx,str); var result2=str2.replace(regx,str); var result3=str3.replace(regx,str); document.write(result1+" "+result2+" "+result3);
另一个答案,一个回复的朋友提的建议:
3.2
前几天遇到一个朋友在群里面问一个问题:他有形如:"[{chk:'-15-13-2-5-'},{chk:'-1-13-4-5-2-'},{chk:'-1-2-5-'}]"这样的很长的字符串数据,在界面用户选择了"-5-"、"-2-"等里面的若干个,那么希望获取出"{chk:'...'}"这样的数据,里面必须同时存在用户选择的所有选项。不如用户在界面勾选了"-5-"和"-4-",那么最后只有{chk:'-1-13-4-5-2-'}满足条件。
答案:
//此数组为用户界面选择的选项组合而成,不能为空 var strArray=["-5-","-4-"]; var str=""; //进行组合部分正则表达式,这里的表达式组合为只要包含数组里面的元素就取出来 for(var i=0;i<strArray.length;i++) { if(strArray.length==1) { str=strArray[0]; } else { if(i==0) { str+="(?:"+strArray[0]; } else if(i==strArray.length-1) { str+="|"+strArray[i]+")"; } else { str+="|"+strArray[i]; } } } //组合完整的表达式 str="(\\{chk:'[-\\d]*"+str+"[-\\d]*'\\})"; //用户的字符串数据 var myData="[{chk:'-15-13-2-5-'},{chk:'-1-13-4-5-2-'},{chk:'-1-2-5-'}]"; var rexg = new RegExp(str,"g"); //返回包含用户选择的条件的所有数据 var array=myData.match(rexg); var arrayLast=[]; var count=0; //循环遍历,抽取出满足用户选择所有条件的数据 for(var j=0;j<array.length;j++) { for(var k=0;k<strArray.length;k++) { var re=new RegExp("(\\{chk:'[-\\d]*"+strArray[k]+"[-\\d]*'\\})","g"); if(!re.test(array[j])) { break; } else { if(k==strArray.length-1) { arrayLast[count++]=array[j]; } } } } alert(arrayLast);
希望对大家有所帮助吧!