1 正则表达式的字符匹配攻略
正则表达式是匹配模式,要么匹配位置,要么匹配字符
字符匹配攻略
1.1 两种模糊匹配
-
横向模糊匹配:其实现的方式是使用量词,比如 /ab{2,4}c/ 表示字符b出现2-4次;
量词:量词也简称重复,表示一个字符可以出现的次数{m,n} 最少m次,最多n次;
贪婪匹配和惰性匹配:量词本身的匹配是贪婪的,也就是说会尽可能多的匹配;但是通过在量词后面加一个 ? 就可以表示惰性匹配,表示尽可能少的匹配;
量词 具体含义
{m,} 表示至少出现m次
{m} 等价于{m,m},表示出现m次
? 等价于{0,1},表示出现一次或者不出现 /a?/:表示字符a 出现一次,此时匹配到a ; 0次,此时匹配到空字符串''
等价于{1,},表示至少出现一次
等价于{0,表示出现任意次数,有可能不出现,此时匹配空字符串
贪婪量词 惰性量词
{m,n} {m,n}?
{m,} {m,}?
? ??
+?
*?
-
纵向模糊匹配:其实现方式是使用字符组,比如 [abc],表示该字符可以匹配 'a' 'b' 'c'
字符组[abc] : 还可以使用范围表示法 a-z;仅仅是表示其中的一个字符;
排除字符组1:表示除 a. b c 之外的任意一个字符;
简写字符组:对于字符组,肯定有着相应的简写形式
字符组 具体含义
d [0-9]:表示一位数字
D 2: 表示除数字外的任意一个字符
w [0-9a-zA-Z_]:表示数字,大小写字母,下划线中任意一个字符;
W 3:表示除了数字,大小写字母,下划线中的其他任意一个字符
s [ tvnrf] :表示空白符,包括空格,水平制表符,垂直制表符,换行符,回车符,换页符
S 4:表示非空白符
如果想要匹配任意一个字符,那么可以使用 [/d/D],[/w/W],[/s/S],[^] 中的任意一个都可以;
1.3 多选分支(惰性匹配,如果匹配到了,则后面的就不在进行匹配)
/hello|world/
var str = 'abc'; console.log(str.replace(/^|$/g,'#')); //如果没有加 g; #abc ;如果加了 g: #abc#;
测试案例
匹配24小时制时间
var reg = /^([01][1-9]|[2][0-3]):([0-5][0-9])$/; // 23:59 // 02:19
2 正则表达式的位置匹配攻略
将位置可以理解成一个空的字符串 : '',一定要牢记这句话;
也就是说在一个字符串中找到相应的位置,找到位置之后,对该位置进行操作;
2.1 在ES5中有如下几个表示位置的锚:^. $ b. B. (?=p) (?!p)
首先,丢掉其他地方看的一些^ $的解释,以什么什么开头,或者以什么什么结尾,要从位置可以理解为(空字符)的角度去看待这些符号;
^ 匹配到的位置是一个字符串的开头位置;
$ 匹配到的位置是一个字符串的结尾位置;
b 是单词边界,具体就是 w([0-9a-zA-Z_])和W之间的位置,也包括 w 与^ (开头)$(结尾) 之间的位置
B 是非单词边界,具体就是 w与w;W与W ; W与 ^ $(开头,结尾)
var str = '[a b[JS]c.lesson'; console.log(str.replace(/\b/g,"#")); //[#a# #b#[#JS#]#c#.#lesson# console.log(str.replace(/\B/g,"#")); //#[a b[J#S]c.l#e#s#s#o#n
(?=p) 代表p前面的位置或者说该位置后面的字符要匹配p ;
(?!p) 代表和上面相反的意思;
//看下这个,全局匹配会替换掉全局中匹配到的字符 /a+/g ; var str3 = 'aalllaaaaaxxxxxaffffaaaaaggg'; var reg3 = /a+/g; console.log(str3.replace(reg3,',')); //,lll,xxxxx,ffff,ggg //以下重点理解下(?= p)这个匹配p前面的位置(空字符),在下面这个案例中p是 (\d{3})+$,它将匹配到三个字符 // 646;654646 ; 254654646 所以(?=(\d{3})+$)代表着三个字符前面的位置(空字符)然后将该字符替换成 ','; var str2 = '1254654646' var reg2 = /(?=(\d{3})+$)/g; console.log(str2.replace(reg2,'); //1,254,654,646 //但是对于123456789 =>,123,456,789;所以不能匹配到开始的位置,(?!^)就可以实现; var reg2 = /(?!^)(?=(\d{3})+$)/g;
3 正则表达式的括号的作用
3.1 分组引用
var reg = /(\d{4})-(\d{2})-(\d{2})/; var str ='2019-02-24'; console.log(str.match(reg)); console.log(reg.exec(str)); //两者的输出都是: ["2019-02-24","2019","02","24",index:"0","2019-02-24"]
3.2 RegExp的全局属性 $1至$9
//对于上面的案例在加以下代码 console.dir(RegExp); //[$1:'2017',$2:'02',$3:'24',$4:'',$5:'',$6:'',$7:'',$8:'',$9:'',$&:'2019-02-24',$`:'',$';'',$+:'24',$_:'2014-02-24']; console.log(RegExp.$1); console.log(RegExp.$2); console.log(RegExp.$3);
3.3 对于常用API中使用分组引用;
3.3.1 str.replace(regexp|substr,newSubstr|function) ;
对于newSubStr : $$(表示插入一个$). $n. $` $' $&. 就是上面分析的结果
对于function:该函数接受参数,(match,p1,p2,…pn,offset,string)
match: 匹配到的子串 ;p1,p3 ..: 第几个分组 ; offset:匹配到的子串在整个字符串中出现的位置;string:整个被撇配的字符串
console.log(str.replace(reg,'$3/$2/$1'));//24/02/2019 var retDate = str.replace(reg,function(match,p3,str){ console.log(arguments); //["2019-02-24","2019-02-24",...] return [p3,p1].join('/'); }); console.log(retDate);//24/02/2019;
3.3.2 str.match(reg) :当一个字符串与一个正则表达式匹配时, match()方法检索匹配项。
参数reg:1 如果未提供任何参数 ,直接使用match(),那么会返回一个[""];2 如果传入一个非正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp
-
如果正则表达式没有 g全局匹配标识,那么返回的数组中只有第一个匹配的字符,其中还包括两个属性 index表示匹配字符串在原字符串中的索引位置;input表示被解析的原始字符串;
var regex = /ab{1,6}c/i;
var str = 'abcabbcabbbcabbbbc';
var ret = str.match(regex);
console.log(ret);
//["abc",index: 0,input: "abcabbcabbbcabbbbc"]
//? 表示匹配0次(代表空字符串''),1次代表字符串
var liangStr = 'avs';
var liangReg = /[fbc]?/;
var liangRet = liangStr.match(liangReg);
//liangRet:["",input: "avs"] -
如果正则表达式包含 g全局匹配,那么会将全局匹配到的结果全部放到数组中,此时没有input和index属性;
var regex = /ab{1,6}c/g;
var str = 'abcabbcabbbcabbbbc';
var ret = str.match(regex);
console.log(ret);
// ["abc","abbc","abbbc","abbbbc"]
3.3.3 str.search(regexp) :检索一个字符串中是否可以匹配到相应的正则,返回匹配到正则结果在字符串中出现的索引,如果匹配不到则返回 -1
var reg = /[A-Z]/g; var str = 'abcAFs'; console.log(str.search(reg));//3 返回匹配到的结果在字符串中的索引位置,注意位置是从 0 开始的
3.4 反向引用:除了在API中可以引用分组,也可以在正则本身中引用分组,但是只能引用前面出现的分组
//比如要写一个正则匹配如下三种格式 2014-08-23 2014.08.24 2014/08/24 var reg = /\d{4}(-|\.|\/)\d{2}(-|\.|\/)\d{2}/ //这个正则虽然可以匹配到以上三种格式的数据,但是也会匹配到 2014.08/24 这样的数据
此时就需要反向引用
var reg = /\d{4}(-|\.|\/)\d{2}\1\d{2}/; //此时的 \1 就代表前面的(-|\.|\/)这个分组,无论这个分组匹配到什么,\1 都会匹配到和它一样的具体的某个字符 //这样就不会出现匹配到。2014.08/24 这样的错误了;
对于括号的嵌套,以作括号为基准,作为每个分组的匹配结果;
3.5 捕获括号
以上介绍了捕获括号,也就是捕获型分组会在API或者正则种被捕获,如果我们对一个括号仅仅是希望其匹配到对应的字符,而不需要捕获,那么,可以使用
(?:p) //非捕获型分组 (p) //捕获型分组
4 正则表达式的结构和拆分
4.1 结构和操作符
-
javascript中的正则表达是中有哪些结构呢?:字符字面量,字符组,量词,锚,分组,分之,反向引用
结构 说明
字面量 匹配一个具体的字符,包括需要转义和不需要转义的;'a' '.'
字符组 匹配一个字符,但是这个字符可以是多种可能性之一;[0-9] :匹配一个数字;2匹配一个非数字;
量词 表示匹配到的字符连续出现的次数;/a{1,3}/
锚 匹配一个位置;^ 开始位置;$ 结束位置 ; ;(?=p) : p前面的位置(注意对位置的理解要从一个空字符串的角度理解
分组 /(ab)+/:表示‘ab’连续出现多次;也可以使用非捕获型分组 /(?:ab)+/
分之 多个字表达式多选一:abc|def ;可以匹配abc或者def; -
操作符包括 转义 ;() 和[ ] ;量词限定符;位置和序列 ^ $ ;管道符 | ;
操作符描述 操作符
转义符
括号和方括号 (p ) (?=p). (?:p) (?!p) [p]
量词限定符 {m} {m,n} ? * +
位置和序列 ^. $
管道符 |
优先级从上至下;
5 正则表达式其余操作
regExp.test(str) :当你想要知道一个模式是否存在于一个字符串中时,就可以使用 test()(类似于String.prototype.search()方法),差别在于test返回一个布尔值,而 search 返回索引(如果找到)或者-1(如果没找到)
var reg = /[A-Z]/g; var str = 'abcAFs'; console.log(reg.test(str));//true
-
regExp.exec(str) :方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。
如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的属性。返回的数组将完全匹配成功的文本作为第一项,将正则括号里匹配成功的作为数组填充到后面。
如果匹配失败,exec() 方法返回 nullvar reg = /[0-9]/g;
var str = 'abcAFs';
console.log(reg.exec(str)); //null
千分位分隔符