正则整理

正则整理

一:定义

 正则是模式 ,模型,是用来匹配验证字符串的  
   1,定义模式 RegExp
   2,匹配  .test方法   RegExp.prototype.text
   3,捕获  . exec方法 返回的是数组,会把所有匹配项保存到数组里,如果正则和字符串不能匹配,则返回null。

   1字面量  var reg=/\d/;
   2new    var reg=new RegExp("\\d");
   eg:   var str="孙" ;  reg=new RegExp("^"+str+"[\\u4300-\\u9fa5]+$"); //构造函数灵活

var reg =/^\d$/;
//^表示必须以后边的字符开始,修饰的是后边的符号。\d表示0-9之间的一个数字
//$以他前边的衣服结尾,修饰的是前边的符号。
//+量词,修饰前边的字符出现一道多次的,相当于{1,}
//元字符:在正则中表示一些特定含义的字符叫元字符。正则中不仅可以有元字符,正常的字符同样可以出现。
reg = /1234/; "a1234b","398551234095"
reg=/^1234$/;
reg = /^[a-z]{1,}$/;          //验证是不是全是字母 。 []表示多选一的“或”,或者表示连续出现的字符中的某一个
reg=/^[a-z]+$/i ;             //出现在正则后边的字符叫模式修正符,在js中,只有三个修正符g、i、m。i表示忽略大小写,g表示全文查找,m表示多行查找。

var reg=/(ab|cd|xyz)/ ;                //表示验证一个字符中,只要出现了ab或cd或xyz则成功;"149abs3"

var reg1=/^\d+(ab|cd|xyz)\d+$/;       //ab或cd或xyz的前后必须是数字
var reg2=/^\d+ab|cd|xyz\d+$/;          //区别下面的有括号的正则

var str1="48940xyz930"          //reg1.exec(str1)   ==>返回["48940xyz930","xyz"]
var str2="390ab";
var str3="4902abcd";           //  reg2.exec(str3)  ==>返回["4902ab"]
var str4="cd930ab";
var str5="xyz999ab";

var str6="84949@qq.com"//需要证邮箱
//邮箱:首先要给出你的网站规定的邮箱规则

//包括数字,字母,下划线和., 后边是@,再后边域名,再后是.点,最后的部分只能是字母
regMail=/^[\w.]+@\w+\.[a-z]+(\.[a-z]+)?$/i
//[+*]/ ;
//【【在[]里的单字符的元字符,不用转意,就表示这个字母表示的本身的意思】】
//量词元字符:+一到多次,*零到多次,?零到一次,{m,n},{m},{m,}
var regMail=new RegExp("^[\w.]+@\w+\.[a-z]+(\.[a-z]+)?$","i");

//在[]里的单字符的元字符不用转意,就表示字母的本身的意思
//量词元字符:?零到一次、 *零到多次、 +一到多次、{m,n}、 {m}、{m,}
var reg3=/^1234$/
var str7="asd1234"

二:非贪婪匹配

var innerHTML=document.body.innerHTML;
. [\s\S] [.\n];单字符的元字符,一但放到[]里,就失去了元字符的功能了
//就说是[.]和\.一样了
//+?*()|{} 
//表示所有的字符的方式有[\s\S],[\D\d],[\w\W],(.|\n)这个方式有可能存在bug。
//但是[\B\b]这个不可以表示任意字符
var reg=/<div +id="content">[\s\S]+<\/div>/;//不带?,则按着贪婪匹配的方式,捕获到最后一个</div>
console.log(reg.exec(innerHTML)[0]);
var reg=/<div +id="content">[\s\S]+?<\/div>/;//在+后带?,则按非贪婪匹配的方式捕获到最近的一个</div>就结束
console.log(reg.exec(innerHTML)[0]);    

三:问号的几种意义

//量词
var reg=/^a?$/   //要么是个空字符串,要么只是一个a,出现在实意字符的后边他表示这个实意字符出现0到1次,即是个量词
//非贪婪模式
var reg=/^a+?$/    //这次的?就不是量词了  表示非贪婪模式
var reg1=/\d+/
var reg2=/\d+?/
reg1.exec("ad123445533jk");   // 输出 ["123445533"]
reg2.exec("ad123445533jk")    // 输出 ["1"]

var reg1=/^\d+(ab|cd|xyz)\d+$/;//ab或cd或xyz的前后必须是数字
var str1="48940xyz930";
reg1.exec(str1);//输出结果是["48940xyz930","xyz"];

//分组中的(子正则匹配不捕获)
//把?:放在括号的开始位置,表示不再把括号的内容当成一个子正则(匹配不捕获)取消分组
var reg2=/^\d+(?:ab|cd|xyz)\d+$/;//ab或cd或xyz的前后必须是数字
var str1="48940xyz930";
reg1.exec(str1);//输出结果是["48940xyz930"]


//前提条件(断言assert)
//正向预查和负向预查(带条件的正则表达式)

//条件是匹配以字符结尾的连续数字的正则
var str2="did4905dkd77d&#"
var str3="did4905dkd89dac"

var reg3=/\d{2,}(?=[a-z]+$)/;//括号里的根本就不参与捕获,只是这个正则成立的条件(前提),【只修饰左边的】
var reg4=/\d{2,}(?:[a-z]+$)/;//这是取消分组,但是可以把89dac捕获到,但不会把dac单独再捕获到了
var reg5=/\d{2,}([a-z]+$)/;
var reg6=/\d{2,}[a-z]+$/
reg3.exec(str2);//null
reg3.exec(str3);//["89"];
reg4.exec(str3);//["89dac"];
reg5.exec(str3);//["89dac","dac"]
reg6.exec(str3);//["89dac"]

//负向预查
var reg7=/\d{2,}(?![a-z]+$)/;//(?后面不全是字母)

var str2="diddkd77d&#";//虽然也是在77后边有字母d,但d不是结尾,满足了正则的定义
var str3="diddkd89dac";//这个是以连续的多个字母结尾的,不满足reg5中规定的条件,所以匹配不成功
var str4="diddkd894dac";//对于这个字符串,奇葩的问题就出现了。把89看成满足条件的部分了,89后边是4,不是字母,按成立来对待了。
//需要注意的是:在写负向预查的正则时,尽量的严格,慎用。
//正向预查和负向预查是尽量的让条件部分满意
reg7.exec(str2);  //["77"]
reg7.exec(str3);  //null
reg7.exec(str4);  //["89"]

var reg8=/\d{2,}([^a-z]+$)/ ;//(?后面不出现字母)
var str5="diddkaj4758*%$("
reg8.exec(str2);       //null
reg8.exec(str3);       //null
reg8.exec(str4);       //null
reg8.exec(str5);       //["4758*%$(","*%$("]

四:分组

//子正则:小括号
//如果验证重复的字符怎么办?
var str1 = "aaaaaaaa";
var str2 = "abcdefg";

//分组的概念  ()
var reg = /((\w)(\w)(\w))/;
reg.exec(str1);         //["aaa", "aaa", "a", "a", "a"]
reg.exec(str2);         //["abc", "abc", "a", "b", "c"]

//分组的引用   如果正则没有加g 则exec和match功能一样
var reg = /^(\d)\d\1$/;
var str3 = "121";
str4 = "212";

var reg = /^(\w)\1+$/;
var str = "aaa";
//alert(reg.exec("aaaaaa"));     //["aaaaaa","a"]
reg.exec(str);      //["aaa", "a"]

//用其它方式获得分组(子正则)捕获到的内容

var reg = /(\w)(\w)(\w)/;

var str = "abcdefghighlmn";
reg.test(str);    //true
reg.exec(str);   //["abc", "a", "b", "c"]
//正则实例运行之后,如果此正则上有分组,则会自动把分组捕获到的内容分别赋值给构造函数的$1,$2,$3.....$9
RegExp.$1;   //"a"
RegExp.$2;   //"b"
RegExp.$3;   //"c"
/*RegExp.$4;   //"" 空字符串
RegExp.$5;  //""
RegExp.$9;   //""
RegExp.$_;   //"abcdefghighlmn"*/

五:元字符

// 实意元字符  \d\w\s
//非实意字符(表示某种逻辑)  \b   分割常用的\w和不常用的\W的   str"abc@你好zxv%f**998"
//表示位置的元字符
   var reg=/^\s*$/;       //一般来做空验证或非空验证
//表示数量的元字符
// + {1,n} * {0,n} ? {0,1}    【【 不知道多少空格可以用+】】

//转意字符 \             [.] 和\.  一样了
//表示元字符本身的时候,需要用\转意一下。
//var reg=/[^a-z]/;//取非集;除a-z之外的任意字符

// 逻辑运算的或运算
    //[abcdef]//    其中任意一个
    //左|右//
//表示所有的字符方式有   [\s\S] [\d\D] [\w\W]     但是[\b\B] 不可以
\d \D这是\d的非集
\w [A-Za-z0-9_]  常用字符集(大小写字母、数字、下划线)  \W [^A-Za-z0-9_]
\s  一切不可见的字符集(空白字符)
\S
[0-9]
[xyz]        匹配所包含的任意一个字符
[0-100]   0 1
. 除换行回车外的任意一个字符
\n   string换行符

如果想匹配任意字符怎么办呢?

reg=/^(.|\s)+$/;
reg=/^[\S\s]+$/;"abcddi9d","aaaaaaaa"


//	var reg=/^[\d\D]+$/;
//	var str="a1,3.4/52-=&*24jsk"
//    reg.exec(str);   // ["a1,3.4/52-=&*24jsk"]
//
//
//	var reg=/[abc]/;
//	reg.exec(str);    //["a"]
var reg1=/MSIE (6|7|8|9|10)/;
var str=window.navigator.userAgent;
console.log(str);
reg1.test(str);
reg1.exec(str);
console.log(reg1.exec(str));
console.dir(reg1.exec(str));
console.log((reg1.exec(str)) instanceof Array);
console.log(Object.prototype.toString.call(reg1.exec(str)));

六:模式修正符

//i,m,g    是对正则功能的补充
var reg = /^\d/img;
// reg.ignoreCase;//如果不设置修正符i,则这个属性的值是false
// reg.multiline; //同理上面的i  ,只用在加了^ 或$,并且字符串中有换行字 符的前提下才有意义,并且一般情况下和g连用
// reg.global;

reg = /^\d+/mg;//多行全局查找,m只有当字符串中加了换行的时候才有意义
reg2 = /\w$/
var str = "2dkdf\n3dkdi\n4dkdk\n5kdkd";
var a = str.match(reg);
// alert(a);               //["2", "3", "4", "5"]
console.log(a);

var str = "192.168.1.100";
str.split(".");
var reg = /\d+/g;
//alert(str.match(reg));    //["192", "168", "1", "100"]

//alert(reg.exec(str));   //按点击弹出:["192"] ["168"] ["1"] ["100"] null ["192"] ......在执行的时候吗,会去根据两个属性值去实现捕获    reg.lastIndex的值默认是0; 它是本次正则匹配的起始索引位置。
//reg.global 如果是false 则正则只做一次查找,reg.lastIndex的值永远是0;
//reg.global如果是true 会自动修改reg.lastIndex的值 将其修改为本次匹配结果的后边字符的索引位置,
//如果当次匹配没有成功(test返回了false,exec返回了null) 则会重置reg.lastIndex的值为0;

//简单的正则捕获中 尽量用match方法
  str.match(reg);

RegExp.prototype.allExec= function (str) {
    if(this.global){
        this.lastIndex=0
        var a=[];  //存放每一次捕获到结果
        var result=null;
       while(  result=this.exec(str)){
           a.push(result);
       };
        return a;
    }else{
        return this.exec(str);
    }
}


var reg1 = /\d/g;
var str1 = "abcdef8";
reg1.test(str1);//true;
var str2 = "4abcdefg";
reg1.test(str2);//false //true  //false  //true

七:replace方法

var str="abc";//把此字符串反转成cba

str.replace(/(\w)(\w)(\w)/,"$3$2$1");

var str0="123456973";

//凡是值类型的上的方法,都不会修正原实例
var newStr=str0.replace(/\d/g,"a");

//下面的数组只是为了让索引1和a对应,索引2和b对应......

var a=["","a","b","c","d","e","f","g","h","i"];
var newStr=str0.replace(/\d/g,function(){
	//此正则每匹配到一次字符,则运行一次此方法,并且传三个参数给这个方法,分别的0当次正则捕获到的结果,1是此结果在输入字符串中的索引位置,2是输入字符串
	//return a[arguments[0]];
	//要求是:把1转成A,2转成大写B,3--C
	return String.fromCharCode(64+arguments[0]/1);
	//String.fromCharCode是把ASCII码转成字符
	//65是A,64+1是A,
});

八:反转字符的两种方法

var str="abcdefg"
// 0123456	
//str.split("").reverse().join("");//这是简单粗暴的方法
var newStr=str.replace(/\w/g,function(){
	//str.length-1-arguments[1]//计算和当前字符对称的字符的索引位置

	//找到对称位置上的字符并返回,这样则把原位置和对称位置上的字符交换了,实现了字符串的反转
	//比如第一次运行时找到a的索引0,通过这个0找到和a对称的字符g(第0个和最后一个对称),然后让g替换a
	return str.charAt(str.length-1-arguments[1]);
});
alert(newStr);
//第二种写法
var newStr=str.replace(/\w/g,function(a,b,c){
	return c.charAt(c.length-1-b);	
});

九:字符串去重

var str = "88888889999993333337777777222222";
var reg = /(\w)\1+/g;
//str.match(reg);
var newStr=str.replace(reg,function(a,b,c,d){
 //1.总正则捕获到的结果  2.总结果在字符串中的索引位置  3.原字符串
 //如果正则中有分组,则会在1和2之间,把每个分组捕获到的结果,当参数传进来
    console.log(a,b,c,d);
 return b;
 });
 console.log(newStr);

十:千分符的几种写法

//加上千分符后的结果如下:
//"7,654,321"

//思路:先不考虑从后往前加逗号,先考虑从向往后加逗号
"765,432,1"
str1=str.replace(/(\d{3})(?!$)/g,"$1,");
///(\d{3})(?!$)/g的(?!$)表示连续出现的三位数字的后边不能是字符串的结尾,这里使用的是负向预查
//alert(str1);

//第二种方法:正向预查
var str="7654321";
str2=str.replace(/(\d{3})(?=\d)/g,"$1,");
//正向预查只是条件,不能与匹配和捕获。
//正则在处理str时,第一次把987和6都计算了,但是987是正则匹配并且捕获的内容,虽然6也要满足,但不参与捕获。下一次再处理些字符串的时候,是从7的后边开始处理,而不是从6的后边处理。就是说(?=\d)只是前边的正则成立的前提条件(这叫assert,一些教材中译作断言)
//alert(str2);


var str3=str.split("").reverse().join("").replace(/(\d{3})(?=\d)/g,"$1,").split("").reverse().join("");

//alert(str3);


//第三种方法

var str="87654321";
//把这个字符串处理两次
	//第一步:把正则拆分两部分87  654321
var str4=str.replace(/^(\d{1,3})((\d{3})+)$/,function(a,b,c,d,e,f){
		return b+","+c.replace(/\d{3}(?!$)/g,function(){
					console.log(a,b,c,d,e,f)
			return 	arguments[0]+",";
		});
	})

//alert(str4);


//第四种方法
var str="87654321";
//加千分符其实是从后往前数,每三位加一个逗号
//问题是如何倒着数索引:正数是0,倒数就是str.length-1-0;正数是1,则倒数是str.length-1-1
//倒数的顺序号是:str.length-1-index;

var str5=str.replace(/\d(?!$)/g,function(a,b,c){

	//先要搞清a,b,c是谁
	var i=c.length-1-b;
	if(i%3===0){
		return a+",";
	}else{
		return a;
	}
})

//alert(str5);
//第五种方法
var str="87654321";
var reg=/(\d)(?=(\d{3})+$)/g
var a=str.replace(reg,"$1,")
console.log(a);
//第六种方法
var reg=/\B(?=(?:\d{3})+\b)/g
str.replace(reg,",")

十一:汇总

1、元字符
  [拥有特殊含义的元字符]
  \d -> 匹配一个0-9的数字,相当于[0-9],和它相反的是\D ->匹配一个除了0-9的任意字符
  \w -> 匹配一个0-9、a-z、A-Z、_的数字或字符,相当于[0-9a-zA-Z_]
  \s -> 匹配一个空白字符(空格、制表符...)
  \b -> 匹配一个单词的边界
  \t -> 匹配一个制表符
  \n -> 匹配一个换行
  . -> 匹配一个除了\n以外的任意字符
  ^ -> 以某一个元字符开头
  $ -> 以某一个元字符结尾
  \ -> 转移字符
  x|y -> x或者y的一个
  [xyz] -> x、y、z中的任意一个
  [^xyz] -> 除了xyz中的任意一个字符
  [a-z] -> 匹配a-z中的任意一个字符
  [^a-z] -> 匹配除了a-z中的任意一个字符
  () -> 正则中的分组

  注意:
  1)关于[]
    a、[+] ->中括号中出现的所有字符都代表的是本身的意思
    b、[12-65] ->这个不是12-65而是1/2-6/5三者中的一个

  2)关于()
    a、分组的作用是改变默认的优先级,例如:/^18|19$/,181、189、119、819、1819...都符合,而不是我们认为的18或19,但是改成/^(18|19)$/就是单纯的18或19了
    b、可以在捕获大正则匹配的内容同时,把分组匹配的内容也进行捕获->分组捕获
    c、分组引用,例如:/^(\d)(\w)\2\1$/,这里的\2是和第二个分组出现一模样的内容,\1是和第一个分组出现一模一样的内容,例如:"0aa0"就符合了


  [代表数量的量词元字符]
  * -> 0到多个
  + -> 1到多个
  ? -> 0到1个
  {n} -> 出现n次
  {n,} -> 出现n到多次
  {n,m} -> 出现n到m次

  注意:
  1)关于?的几种情况
    a、放在非量词元字符后面,代表出现0-1次
    b、放在量词元字符后面,代表取消捕获时候的贪婪性,例如:reg=/\d+/; reg.exec("2015") -> "2015" 但是如果正则这样写 reg=/\d+?/; reg.exec("2015") -> "2"
    c、在分组开头加?:,代表当前的分组只是匹配不进行捕获,例如:/^(?:\d+)$/
    d、在分组开头加?=,正向预查,例如:/^zhufeng(?=1|2)$/ 只有"zhufeng1"和"zhufeng2"才符合
    e、在分组开头加?!,负向预查,例如:/^zhufeng(?!1|2)$/ 除了"zhufeng1"和"zhufeng2"不符合,其他的只要是"zhufeng(任何的东西)"都符合

  [代表本身意思的元字符]
  除了以上的,在字面量方式中,我们出现的其他任意字符代表的都是自己本身的意思
  var num=12;
  var reg=/^\w"+num+"$/; ->这里"+num+"不是把变量的值拼接,而这里的不管是"还是+都是元字符
  ->对于需要拼接字符串和变量的方式我们只能使用实例方式创建正则

2、修饰符
  i -> ignoreCase 忽略字母的大小写
  g -> global 全局匹配 (加上g可以解决正则捕获时候的懒惰性)
  m -> multiline 多行匹配

3、项目中常用的正则
  1)有效数字的
  var reg=/^[+-]?(\d|([1-9]\d+))(\.\d+)?$/;
  var reg=/^[+-]?(\d|[1-9]\d+)(\.\d+)?$/

  2)邮箱的
  var reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;

  3)电话的
  var reg = /^1\d{10}$/;

  4)年龄在18-65之间的
  var reg = /^((18|19)|([2-5]\d)|(6[0-5]))$/;

  5)中文姓名
  var reg = /^[\u4e00-\u9fa5]{2,4}$/;

  6)身份证
  var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(?:\d{2})(\d)(?:\d|X)$/;
  //-> 130828(省市县) 1990(年) 12(月) 04(日) 06 1(奇数是男偶数是女) 7(数字或者X)

4、正则的匹配
  reg.test([string]) ->true就是匹配成功  false->匹配不成功

5、正则的捕获
  1)reg.exec([string])
    -> 首先去匹配,匹配成功在捕获,返回的是一个数组; 如果匹配不成功返回的是null;
    -> 正则的捕获即懒惰又贪婪
    -> 解决懒惰性 在正则的末尾增加全局修饰符g
    -> 解决贪婪性 在量词后面加?

其余更多的参照 "3.2-正则捕获.html"

6、正则实战应用之-replace
  1)获取一个字符串中出现次数最多的字符和对应的次数,例如:var str = "zhufeng2015yangfanqihang";问哪几个字符出现的次数最多,一共有多少次?

  2)千分符
    var str="87654321"
	->str.replace(/(\d)(?=(?:\d{3})+$)/g,'$1,')  只支持整数
	->str.replace(/\B(?=(?:\d{3})+\b)/g,',')   支持小数

  3)模板引擎绑定数据实现的原理
    var ary = ["葛琪", "26", "china", "javascript"];
    var str = "my name is {0},my age is {1},i com from {2},i can do {3}~~";
    ->"my name is 葛琪,my age is 26,i com from china,i can do javascript~~";

  4)单词首字母大写
    var str="my name is zhou xiao tian,my age is twenty five years old~~";
    ->把所有单词的首字母大写

  5)格式化时间
    var str="2015-5-3 12:9:13";
    ->"2015年05月03日 12时09分13秒"

  6)queryURLParameter 获取地址栏中的参数
    http://kbs.sports.qq.com/kbsweb/game.htm?mid=1467588&age=18
    URL问号传参 -> mid=xxxx 就是我们传递过来的内容,我们需要获取mid,并且通过mid区分展示不同的内容
    ->{mid:"1467588",age:18}

  7)在我们的utils.js这个DOM库中很多方法的编写中都使用了部分正则,大家自己回去看一下,尤其是getElementsByClass这个方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值