javascript正则表达式学习

REGEXP对象
javascript通过内置对象RegExp支持正则表达式
有两种方法实例化RegExp对象
1、字面量

var reg = /\bis\b/;
var reg2 = /\bis\b/g; //正则规则放在//内,\bv表示单词边界,g表示全文搜索,如果没有g则只会修改符合条件的第一个值
var str = 'He is a boy. this is a dog. where is she?'
str.replace(reg, 'IS');//"He IS a boy. this is a dog. where is she?"
str.replace(reg2, 'IS');//"He IS a boy. this IS a dog. where IS she?"

2、构造函数
new RegExp(pattern,attributes)接收两个参数
参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。
参数 attributes 是一个可选的字符串,包含属性 “g”、“i” 和 “m”

var reg = new RegExp('\\bis\\b');//两个\\第一个表示转义符
var reg = new RegExp('\\bis\\b');
var reg2 = new RegExp('\\bis\\b', 'g');
'He is a boy. this is a dog. where is she?'.replace(reg, 'IS');//"He IS a boy. this is a dog. where is she?"
'He is a boy. this is a dog. where is she?'.replace(reg2, 'IS');//"He IS a boy. this IS a dog. where IS she?"

正则修饰符介绍

g: global全文搜索,不添加,搜到第一个匹配即停止,后面符合条件的不会被替换
i:ignore case 忽略大小写,默认是大小写敏感的
m:multiple lines多行搜索

"He IS a boy. this IS a dog. where is she?".replace(/\bis\b/gi, 'a');//全文搜索且不区分大小写"He a a boy. this a a dog. where a she?"

**

元字符与元义文本字符

**
元义文本字符:原本的字符的意思,比如abc就是指abc
元字符:有特殊含义的非字母字符,比如* + ? $ ^ . | \ () {} []

字符含义
\t水平制表符
\v垂直制表符
\n换行符
\r回车符
\0空字符
\f换页符
\cX与X对应的控制字符(ctrl + X)

备注:元字符的含义不是唯一的,在不同的情况有不同的含义,例如^在中括号[]内为取反的意思,在别的地方还有以xxx开始的意思
字符类

'ab\tabc-abd'.replace(/ab\t/, '11'); //一一对应"11abc-abd"
//用[]泛指一个简单的类,有[]中的任何一个都会替换
'a1b2c3d4'.replace(/[abc]/g, 'x'); //包含abc的任何一个都被替换为x,而非将abc替换为x "x1b2c3d4"
//取反
'a1b2c3d4'.replace(/[^abc]/g, 'x');//"axbxcxxx" 不是a或者b或者c的都被替换

范围类
[a-z] 从a到z的任意字符,是一个闭区间,包含a和z本身

'a1b2c3d4'.replace(/[a-z]/g, 'Q');// "Q1Q2Q3Q4"
'a1b2c3d4'.replace(/[a-c]/g, 'Q');//"Q1Q2Q3d4"
'aA1bBCD2c3d4'.replace(/[a-cA-B]/g, 'Q');//小写大写可以连接,如果是这种写法属于范围,不能替换-   "QQ1QQCD2Q3d4"
'2021-03-31'.replace(/[0-9]/g, 'P');//"PPPP-PP-PP"
'2021-03-31'.replace(/[0-9-]/g, 'P');//"PPPPPPPPPP"

**

预定义类

**
预定义类匹配常见的字符
在这里插入图片描述

字符含义
^以xxx开始
$以xxx结束
\b单词边界
\B非单词边界
'this is a boy'.replace(/is/g, '0');//"th0 0 a boy"不界定单词边界,有is的都被替换包括单词中的字母
'this is a boy'.replace(/\bis\b/g, '0');//"this 0 a boy" 界定单词边界
'this is a boy'.replace(/\Bis\b/g, '0');//"th0 is a boy" 左边为非单词边界,右边为单词边界只有this满足
'@abc@ef@'.replace(/@./g, 'Y');//"YbcYf@"  替换@+任意字符的
'@abc@ef@'.replace(/.@/g, 'Y');//"@abYeY"  替换任意字符+@
'@abc@ef@'.replace(/^@./g, 'Y');//"Ybc@ef@" 替换开头为@
'@abc@ef@'.replace(/.@$/g, 'Y');//"@abc@eY"  替换结尾为@

量词
匹配一个 连续出现 20次 数字的字符串,如果没有量词,则需要连续写20次匹配

字符含义
出现零次或一次(最多出现1次)
+出现一次或多次(至少出现一次)
*出现零次或多次(任意次)
{n}出现n次
{n,m}出现n到m次,包括n和m
{n,}至少出现n次
var res = /\d{3,6}/;
'12abcdssd'.match(res);//null,数字没有出现3到6次
'12abcds54455sd'.match(res);//["54455"],将至少出现3-6次的数字返回,结果为数组的形式
'1255abcds54455sd'.match(res);// ["1255", "54455"]
'12abcds54455sd'.replace(/\d{3,6}/g,'Q');//"12abcdsQsd"
'123abcds54455sd'.replace(/\d{3,6}/g,'Q');//"QabcdsQsd"

贪婪模式和非贪婪模式

//贪婪模式
'12345678'.replace(/\d{3,6}/g, 'X');//"X78" 按照尽可能多的6匹配,而非3匹配成XX78

非贪婪模式:让正则表达式尽可能少的匹配,也就是说一旦成功匹配不再继续尝试

//非贪婪模式
'12345678'.replace(/\d{3,6}?/g, 'X');//"XX78" 数字字符出现3-6次
'12345678'.match(/\d{3,6}?/g);//["123", "456"]

分组
例如:匹配字符串Byron连续出现3次的场景,如果使用量词

//匹配的为Byron单词中n连续出现3次,而非这个单子连续出现3次
'ByronByronByron'.match(/Byron{3}/);//null
'ByronnnaaaaByronnnbbbb'.match(/Byron{3}/g);(2) ["Byronnn", "Byronnn"]
//分组用小括号()括起来
'ByronByronByron'.match(/(Byron){3}/g);//["ByronByronByron"]
//分组中|或的使用
'tellTitle'.replace(/tell|Title/g, 'Q');//tell或者Title "QQ"
'tellitleAAtelTitle'.replace(/tel(l|T)itle/g, 'Q');//tellitle或telTitle,单词中间一个字母不同,而非两个单子不同 "QAAQ"
//反向引用,分组后可以用$来捕获,第一个分组为$1
//将2015-12-25替换为12/25/2015
'2015-02-15'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$1');//"2015"
'2015-02-15'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2');//"02"
'2015-02-15'.replace(/(\d{4})-(\d{2})-(\d{2})/g,$3);//"undefined"
'2015-02-15'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$3');//"15"
'2015-02-15'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2/$3/$1');//"02/15/2015"
//忽略分组,分组内前面加上问号冒号?:
'2015-02-15'.replace(/(?:\d{4})-(\d{2})-(\d{2})/g,'$1');//"02" 此时第一个分组被忽略,第二个分组编号为$1

前瞻后顾
1、正则表达式从文本头部向尾部开始解析,文本尾部方向,称为“前”(通俗的说,像走路,尾部为未走过的路,所以是前面,头部解析过的为走过的路,为后)
2、前瞻:在正则表达式匹配到规则的时候,向前检查是否符合断言
3、后顾/后占:方向相反
4、javascript不支持后顾
5、符合特定断言称为 肯定/正向 匹配;不符合特定断言称之为 否定/负向 匹配

名称正则
正向前瞻exp(?=assert)
负向前瞻exp(?!assert)
正向后顾exp(?<=assert) javascript不支持
负向后顾exp(?<!assert) javascript不支持

exp表示正则条件,括号内为断言部分

//单词字符且单词字符(\w 字母数字下划线)后面为数字,数字为断言部分,不会被替换
'aa22_ab_24'.replace(/\w(?=\d)/g, 'Q');//"aQQ2_abQQ4"
//第一个a虽然是字母,但后面跟的a而非数字不满足断言,所以第一个a不被替换,第二个a满足被替换,第一个2满足数字后面跟数字,所以第一个2也被替换,第一个_后面不是数字不满足断言
'aa22_ab_24'.replace(/\w(?!\d)/g, 'Q');//"Qa2QQQQ_2Q" 断言为不是数字

与正则表达式相关的方法

对象属性:
1、global:是否全文搜索,默认false
2、ignore case:是否大小写敏感,默认false
3、multiline:多行搜索,默认false
4、lastIndex:当前表达式匹配内容的最后一个字符的下一个位置
5、source:正则表达式的文本字符串

//这几个属性是只读的,不能进行设置
var reg1 = /\w/;
var reg2= /\w/gim;
reg1.global;//false
reg1.global;//false
reg1.ignoreCase;//false
reg.multiline;//false
reg2.global;//true
reg2.ignoreCase;//true
reg2.multiline;//true
//不能对这几个属性进行设置,例如
reg1.global = true;
reg1.global;//依然为false

test()方法,RegExp.prototype.test(str)
用于测试字符串参数中是否存在匹配正则表达式模式的字符串,常用语input输入验证

var reg1 = /\w/;
var reg2= /\w/gim;
reg1.test('a');//true
reg1.test('$');//false
//无论执行几次,结果都一样
//但是reg2的结果则有所不同,这是因为lastIndex属性的原因
reg2.test('ab');//true
reg2.test('ab');//true
reg2.test('ab');//false
reg2.test('ab');//true
while(reg2.test('ab')){
   console.log(reg2.lastIndex);// 1 2
}
//因为是全局检测,下次检测记住了上次检测位置,不是每次都从头检测,第一次检测a满足正则表达式,a后面为b所以lastIndex为1,第二次检测b,b后面没有了所以返回false,然后重置为0,所以第四次又变为true
//解决方法,因为test是检测有没有,不管第几次,所以可以不用g标志即可解决
reg1.test('ab');//true

exec()方法,RegExp.prototype.exec(str)
使用正则表达式模式对字符串执行搜索,并将更新全局RegExp对象的属性以反映匹配结果
如果没有匹配的文本返回null,否则返回一个结果数组,数组中有两个属性:
——index 声明匹配文本的第一个字符的位置
——input 存放被检索的字符串 string
非全局调用
调用非全局的RegExp对象的exec()时,返回的数组
1、第一个元素为与正则表达式相匹配的文本
2、第二个是与RegExpObject的第一个子表达式相匹配的文本(如分组,有的话展示,无不展示)
3、第三个是与RegExpObject的第二个子表达式相匹配的文本(如分组,有的话展示,无不展示)

var reg1 = /\d(\w)\d/;
var str= '@1a2bb3c5678';
var ret= reg1.exec(str);
console.log(ret);
 //["1a2", "a", index: 1, input: "@1a2bb3c5678", groups: undefined]
 // 1a2表示与正则表达式相匹配的文本
 // a表示分组的内容
 // index:1  表示匹配的第一个字符,从0开始,1为第二个,所以下标为1
 // input: '@1a2bb3c5678'  被检索的字符串
 var reg2 = /\d(\w)(\w)\d/;//两个分组
 var str2= '@1at2bb3c5678';
 var ret= reg2.exec(str);
 // ["1at2", "a", "t", index: 1, input: "@1at2bb3c5678", groups: undefined]
 //a  t为匹配的分组文本内容
console.log(reg1.lastIndex);//0 非全局g的状态lastIndex是不生效的,没有作用的

全局调用

var reg3 = /\d(\w)\d/g;
var str3= '@1a2bb3c56&8';
// var ret= reg3.exec(str3);
// console.log(reg3.lastIndex, ret);
// var ret= reg3.exec(str3);
// console.log(reg3.lastIndex, ret);
// var ret= reg3.exec(str3);
// console.log(reg3.lastIndex, ret);
// var ret= reg3.exec(str3);
// console.log(reg3.lastIndex, ret);
while( ret= reg3.exec(str3) ){
    console.log(reg3.lastIndex + '\t' + ret.index + '\t' + ret);
    //4	1	1a2,a  1a2后面的b下标为4,1a2的1下标为1,1a2为满足正则条件的文本,a为分组的文本
    //9	6	3c5,c  3c5后面的6下标为9,3c5的3下标为6,3c5为满足正则条件的文本,c为分组的文本
        }

字符串方法
下面的字符串方法也可以用于正则表达式
原理:会将传入的字符串尝试转为正则

'a1b2c3'.search('1');// 1 查找字符串1也可以找到
'a1b2c3'.search(1); // 1 查找数字1也可以找到

1、search方法,String.protatype.search(str/reg)
用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串
返回第一个匹配结果 index(下标),查不到返回-1
search方法不执行全局匹配,它将忽略 g 标志,并且总是从字符串的开始进行检索

var str= 'abdckjj';
str.search('kjj');//4
str.search('qq');//-1
str.search(/j/);//5 只查找第一个j出现的位置
str.search(/\w/);//0  第一个既满足,所以下标为0
str.search(/j/g);//5 会忽略g,依然只返回第一个j出现的位置

2、match方法,String.protatype.match(str/reg)
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置
没有找到则返回null
非全局调用

var str= 'abdckjj';
str.match('jj'); //["jj", index: 5, input: "abdckjj", groups: undefined]
str.match('bd');//["bd", index: 1, input: "abdckjj", groups: undefined]

备注:非全局调用返回结果类似exec方法,区别exec为正则表达式.exec(字符串参数),match为字符串.match(正则表达式参数)

全局调用

var reg4= /\d(\w)\d/g;
var ts = '$1a2b3c4d5e';
ret = ts.match(reg4);
console.log(ret);//["1a2", "3c4"],只返回匹配结果,没有位置也没有分组内容
console.log(ret.index + '\t' + reg4.lastIndex);//undefined	0

3、split方法,String.protatype.split(str/reg)
split() 方法用于把一个字符串分割成字符串数组
也可以传入正则

 'abcdef'.split();//["abcdef"]
 'abcdef'.split('');//["a", "b", "c", "d", "e", "f"]
 'a,b,c,d,e,f'.split(',');//["a", "b", "c", "d", "e", "f"]
 //相当于隐士转换为正则 'a,b,c,d,e,f'.split(/,/);
 'a1b2c3d4'.split(/\d/);//["a", "b", "c", "d", ""]

4、replace方法,String.protatype.replace(str/reg)
replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串

'a1b'.replace('1',2);//"a2b"
'a1b1c1d'.replace('1',2);//"a2b1c1d" 只替换了第一个
'a1b1c1d'.replace(/1/g,2);//"a2b2c2d"  替换了所有

String.protatype.replace(reg, function)
function参数含义
function会在每次匹配替换的时候调用,有4个参数,具体参数个数看是否有分组,有几个分组
1、匹配字符串
2、正则表达式分组内容,没有分组则没有该参数
3、匹配项在字符串中的index
4、原字符串

//将字符串中的所有数字都在原有基础上+1
var str1='a1b2c3d4e5';
var x=str1.replace(/\d/g, function (param, index, origin) { 
   console.log(param,index, origin);        
   //param   匹配的字符串
   //index   匹配字符串的下标
   //origin  原字符串
   // console.log(typeof (param-0));
   // return param-0+1;  //利用减法运算也可以将字符串转为number类型 
   return parseInt(param) +1;     
 })
 console.log(x); //a2b3c4d5e6
 console.log(str1);//a1b2c3d4e5 不会修改原字符串 
 var x2 = str1.replace('a1', 'Q');
 console.log(x2);//Qb2c3d4e5
//将a1b2c3d4e5中的bc去掉
var str2 = 'a1b2c3d4e5';
var y = str2.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, origin){
  console.log(match, group1, group2, group3);
  return group1 + group3
})    
console.log(y); //a12c34e5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值