JS正则表达式

正则表达式(Regular Expression)是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串

一、JS创建正则表达式

1. 创建方式

  1. 字面量创建
    var reg = /正则表达式主体/修饰符(可选)
  2. 构造函数创建
    var reg = new RegExp('\s', 'ig')
    注意:构造函数创建方式第一个参数可以使用变量,因此如果想使用字符串变量来创建正则,只能使用构造函数创建法

2. 修饰符

  • g:global,全文搜索,不添加的话搜索到第一个结果停止搜索
  • i:ingore case,忽略大小写,默认大小写敏感
  • m:multiple lines,多行搜索
    var str = "abcggab\nabcpab";
    var reg1 = /^abc/g;  
    console.log(str.match(reg1));  //['abc']    
    var reg2 = /^abc/gm;          //使用多行搜索
    console.log(str.match(reg2));  //['abc', 'abc']    
    

二、JS正则表达式常用方法

1. 正则对象实例的属性

  • source:正则表达式的源字符串
  • global:是否全局搜索,默认是false
  • ignoreCase:是否大小写敏感,默认是false
  • multiline:多行搜索,默认值是false
  • lastIndex:是当前表达式模式首次匹配内容中最后一个字符的下一个位置,每次正则表达式成功匹配时,lastIndex属性值都会随之改变

2. 正则对象实例的方法

RegExp.prototype.test(str)

测试字符串中是否存在正则表达式模式,如果存在则返回true,否则返回false

RegExp.prototype.exec(str)

将正则表达式模式在字符串中运行查找,如果exec()找到了匹配的文本,则返回一个结果数组,否则返回 null

  • 非全局匹配的情况
    • 多次运行返回同一个值,即字符串中第一个被匹配到的结果
    • 返回一个数组,第一个元素是与正则表达式匹配的文本,第二个元素是正则中第一个子表达式匹配的结果(如果有的话),第三个元素是是正则中第一个子表达式匹配的结果(如果有的话),以此类推
var reg = /\d(\D)(\d)/;

var r = reg.exec('a1b2c3'); 
console.log(r);      // ["1b2", "b", "2"]

r=reg.exec('a1b2c3');
console.log(r);      // ["1b2", "b", "2"]
  • 全局匹配的情况
    • 当正则对象为全局匹配,执行exec()方法时,它会在RegExp实例的lastIndex属性指定的字符处开始检索字符串,当exec()找到了与表达式相匹配的文本时,在匹配后,它将把RegExp实例的lastIndex属性设置为匹配文本的最后一个字符的下一个位置。
    • 可以通过反复调用exec()方法来遍历字符串中的所有匹配文本,当 exec() 再也找不到匹配的文本时,它将返回null,并把lastIndex属性重置为0
var reg=/\d/g; 
while(r=reg.exec('a1b2c3')){ 
    console.log(r.index+':'+r[0]);         //"1:1" "3:2" "5:3"
}

3. 字符串对象实例的方法

String.prototype.search(reg)

search() 方法用于检索字符串中指定的子字符串(参数为子字符串),或检索与正则表达式相匹配的子字符串(参数为正则表达式),返回字符串中第一个匹配的位置,若未找到,返回-1
search() 方法不执行全局匹配,它将忽略标志g,它同时忽略正则表达式对象的lastIndex属性,并且总是从字符串的开始进行检索,这意味着它总是返回字符串的第一个匹配的位置

console.log('a1b2c3'.search(/\d/g));   //1

String.prototype.match(reg)

match()方法将检索字符串,以找到一个或多个与正则匹配的文本

  • 非全局匹配的情况

    • 如果regexp没有标志g,那么match()方法就只能在字符串中执行一次匹配。如果没有找到任何匹配的文本,match() 将返回null。否则它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。
    • 返回的结果数组的第一个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本(如果有的话)
  • 全局匹配的情况

    • 如果regexp具有标志g,则match()方法将执行全局检索,找到字符串中的所有匹配子字符串,若没有找到任何匹配的子串,则返回 null。
    • 如果找到了一个或多个匹配子串,则返回一个数组
var reg = /\d(\D)/;
console.log('a1b2c3'.match(reg));                //["1b", "b"]

var reg = /\d(\D)/g;
console.log('a1b2c3'.match(reg));                //["1b", "2c"]

字符串match()方法和正则exec()方法的区别

  • match()是字符串的方法,参数是正则;exec()是正则的方法,参数是字符串
  • 非全局匹配情况下,二者结果相同
  • 全局匹配且无子表达式情况下,exec()执行一次得到的是第一个匹配的结果,要想获得所有结果,需要进行遍历;而match()得到的是所有匹配结果组成的数组
  • 全局匹配且有子表达式的情况下,exec()执行一次得到的是第一个匹配到的结果和所有子表达式结果组成的数组,而match()方法会忽略子表达式,返回的是所有匹配到的结果组成的数组
//非全局且无子表达式
var reg = /\D\d/;
var str = 'a1b2c3';

console.log(reg.exec(str));           //["a1"]
console.log(str.match(reg));          //["a1"]

//非全局且有子表达式
var reg = /\D(\d)/;
var str = 'a1b2c3';

console.log(reg.exec(str));           //["a1", "1"]
console.log(str.match(reg));          //["a1", "1"]

//全局且无子表达式
var reg = /\D\d/g;
var str = 'a1b2c3';

console.log(reg.exec(str));           //["a1"]
console.log(reg.exec(str));           //["b2"]
console.log(str.match(reg));          //["a1", "b2", "c3"]

//全局且有子表达式
var reg = /\D(\d)/g;
var str = 'a1b2c3';

console.log(reg.exec(str));          //["a1", "1"]
console.log(reg.exec(str));          //["b2", "2"]
console.log(str.match(reg));         //["a1", "b2", "c3"]

String.prototype.replace(reg|substr, replaceStr|function)

字符串替换方法,返回一个由替换值(参数2)替换匹配的模式(参数1)后的新字符串

  • 不改变原字符串
  • 有两个参数
  • 第一个参数是要替换的部分,可以传入正则表达式或者字符串
  • 第二个参数是替换为的部分,可以是一个字符串,或者一个回调函数
  • 默认情况下只替换匹配到的第一个,除非在正则中使用修饰符g

1. 第二个参数为字符串的情况

第二个参数中,如果是字符串,可以使用如下几个特殊模板字符

  • $$插入一个 "$"。
  • $&插入匹配的子串。
  • $`插入当前匹配的子串左边的内容。
  • $'插入当前匹配的子串右边的内容。
  • $n假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第n个子表达式。注意:索引是从1开始
var str = 'abc123def';
var reg = /(\d)\d(\d)/;

console.log(str.replace('123', '$$'));                //"abc$def"
console.log(str.replace('123', '0$&4'));              //"abc01234def"
console.log(str.replace('123', '$`'));                //"abcabcdef"
console.log(str.replace('123', "$'"));                //"abcdefdef"
console.log(str.replace(reg, '$1' + '0' + '$2'));     //"abc103def"

例子1:给两个单词交换位置

//交换两个单词位置

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");  
console.log(newstr);   // Smith, John

2. 第二个参数为函数的情况

str.replace(reg, fn)
可以指定一个函数作为第二个参数,该函数的返回值作为替换字符串,当匹配执行后,该函数就会执行
注意:如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,即每次匹配都会被调用

该回调函数可以接收四个参数

  • 参数1:就是匹配到的字符串(类似上述模板字符的$&)
  • 参数2(可能有多个,取决于正则中是否有分组):如果参数1是正则且有分组,则参数2就是对应的一个或者多个分组结果
  • 参数3:是被匹配到的子串在字符串中的索引位置
  • 参数4:原字符串

例子2:将字符串中的每个数字后添加0

var str = 'a1b2c3d4';
var newStr = str.replace(/\d/g, function(match, index, str){
  //因为全局匹配会匹配到4次,因此会执行4次console.log()
  //match四次分别输出:"1" "2" "3" "4"
  //index四次分别输出:1 3 5 7
  //str每次都输出:"a1b2c3d4"
  console.log(match, index, str);    
  return match + 0;          //给每个匹配到的字符串后面添加个0,作为新字符串
});
console.log(newStr);        //"a10b20c30d40"

例子3:给不同分组间添加'-'

function replacer(match, p1, p2, p3) {
  //p1、p2、p3表示正则中匹配到的分组(子表达式)
  console.log(p1, p2, p3);       //"abc" "123" "#$*"
  return  p1 + '-' + p2 + '-' + p3;
}
var newString = 'abc123#$*'.replace(/([\D]*)(\d*)([\W]*)/, replacer);
console.log(newString);  // abc-123-#$*

String.prototype.split(reg)

分割字符串,当字符串作为参数无法满足要求时,也可以传入正则对象作为参数,来将字符串分割为数组

'a1b2c3d'.split(/\d/);      //["a", "b", "c", "d"]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355