正则大全

我们在开发中经常会用到正则匹配,但是里面内容庞大实在难以记清,今天我们就来梳理一下正则知识,并在最后送上一些经常用到的匹配方案,毕竟自己也是很害怕这一块的。
1.replace
关于replace的用法,其实很多,我们会仔细讲解。

var re = /apples/gi;
var str = "Apples are round, and apples are juicy.";
var newstr = str.replace(re, "oranges");

// oranges are round, and oranges are juicy.
console.log(newstr);

最基本的用法,g全局匹配,i忽略大小写。

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
// Smith, John
console.log(newstr);
交换了2个单词的位置

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

\s是匹配空格,$&是匹配的子串,$1,$2分别字匹配项。
再来看一个

function replacer(match, p1, p2, p3, offset, string) {
  // p1 is nondigits, p2 digits, and p3 non-alphanumerics
  return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);

这里我们一目了然了把,看replcaer里面的参数就知道了。

我想问一下大家知道$&和replacer函数里面最后一个参数string有啥区别
其实我刚刚做了个实验,但是发现有问题,就先不说了,等下会有结论再讲吧。

function f2c(x)
{
  function convert(str, p1, offset, s)
  {
    return ((p1-32) * 5/9) + "C";
  }
  var s = String(x);
  var test = /(\d+(\.\d*)?)F/g;
  return s.replace(test, convert);
}

函数传入一个x,将其从华氏温度转成摄氏度。

2.exec
exec是正则里面会比较频繁用到的,想想jquery的源码,里面充斥的这样的匹配。

var str = "javascript html css 555";
console.log(/(html) (css) (\d*)/.exec(str)); // ["html", index: 11, input: "javascript html css"]
output:
 ["html css 555", "html", "css", "555", index: 11, input: "javascript html css 555"]

可以看出来exec方法,会返回一个数组,第一个元素是符合匹配的字符串合集,第二个到第n个是表达式的子项,index是符合首个匹配的索引,input是源字符串。

var x = " a.xxx.com b.xxx.com c.xxx.com";
var re = /\s?(.*?).xxx.com/g;
while( tempR = re.exec(x))
{
 console.log(tempR);
}
output:
[" a.xxx.com", "a", index: 0, input: " a.xxx.com b.xxx.com c.xxx.com"]
[" b.xxx.com", "b", index: 10, input: " a.xxx.com b.xxx.com c.xxx.com"]
[" c.xxx.com", "c", index: 20, input: " a.xxx.com b.xxx.com c.xxx.com"]
//一般用于循环,将所有的匹配都输出出来,注意(.*?)匹配任何东西。

再来最后一个例子

var myRe = /ab*/g;
var str = 'abbcdefabh';
var myArray;
while ((myArray = myRe.exec(str)) !== null) {
  var msg = 'Found ' + myArray[0] + '. ';
  msg += 'Next match starts at ' + myRe.lastIndex;
  console.log(msg);
}
output:
Found abb. Next match starts at 3
Found ab. Next match starts at 9

注意lastIndex是指匹配的末项索引。

3.search
这个没啥其他扩展,咱们一笔带过

var str = "hello world,hello world";
// 返回匹配到的第一个位置
console.log(str.search(/hello/)); // 0
// search方法不执行全局匹配,它将忽略标志g,同时它也没有regexp对象的lastIndex的属性,且总是从字符串开始位置进行查找,总是返回的是stringObject匹配的第一个位置。
console.log(str.search(/hello/g)); //0
console.log(str.search(/world/)); // 6

search方法都是从第一个位置开始查找,并且没有全局g的标志。

4.match
初级用法和exec差不多,但是他全局匹配可以返回一个所有符合正则的数组。

var str = "hello world";
// 返回的数组内有三个元素,第一个元素的存放的是匹配的文本,还有二个对象属性;
index属性表明的是匹配文本的起始字符在stringObject中的位置;input属性声明的是
对stringObject对象的引用;
console.log(str.match("hello")); // ["hello", index: 0, input: "hello world"]

var re = new RegExp('([0-9]+)-([0-9]+)-([0-9]+)');
var str = '2016-01-02';
var result = str.match(re); 
console.log(result.)); // [2016,01,02]

用了全局方法后会得到一个所有符合匹配的数组。

基本用法咱们讲解完毕,我们来看一下高阶用法。
1.贪婪模式和懒惰模式
相信大家对这个已经有所耳闻了,那我们来看到底是啥。

var txt = '<a href=”http://google.com”>谷歌</a><a href=”http://baidu.com”>百度</a>'
var re1 = /\<a (.*?)\<\/a\>/g; //懒惰模式,尽可能少的匹配

console.log(re1.exec(txt)); 
//["<a href=”http://google.com”>谷歌</a>", "href=”http://google.com”>谷歌"]

console.log(re1.exec(txt));
//["<a href=”http://baidu.com”>百度</a>", "href=”http://baidu.com”>百度"]
这个是懒惰模式,跟我们之前讲的exec并没有啥区别,接着看下面这个。

var re2 = /\<a (.*)\<\/a\>/g; //贪婪模式,尽可能多的匹配, 区别在不加问号
console.log(re2.exec(txt));
//["<a href=”http://google.com”>谷歌</a><a href=”http://baidu.com”>百度</a>", 
//"href=”http://google.com”>谷歌</a><a href=”http://baidu.com”>百度"]
console.log(re2.exec(txt));
//null
相信大家已经看粗什么端倪来了,贪婪模式会把a标签中间所有的都检索到,所以到值exec执行一次
就没有下文了。

2.捕获分组和非捕获分组
看起来却是一脸蒙蔽,我们简短说一下吧,毕竟这个属于很少用的。

var str = "a1***ab1cd2***c2";  
var reg1 = /((ab)+\d+)((cd)+\d+)/i; 
var reg2 = /((?:ab)+\d+)((?:cd)+\d+)/i; 
console.log(str.match(reg1));
output:
["ab1cd2", "ab1", "ab", "cd2", "cd", index: 5, input: "a1***ab1cd2***c2"]
我们发现第二层括号里面的居然也北大引出来了,我们其实只想要外层的匹配
console.log(str.match(reg2));
output:
["ab1cd2", "ab1",  "cd2", index: 5, input: "a1***ab1cd2***c2"]

其实捕获和不捕获就是指的匹配想得子项是否被归入到结果中,如果还不够明白请看下面

var reg = /(?:\d{4})-(\d{2})-(\d{2})/
var reg1 = /(\d{4})-(\d{2})-(\d{2})/
var date = '2012-12-21'
reg.test(date)
RegExp.$1  
"12"
奇怪了第一个匹配的\d{4}明明是2012,为什么会输出12呢
reg1.test(date)
RegExp.$1  
“2012”

反正我已经是领略到了,如果还有疑问可以看mdn开发文档

3.零宽断言
零宽断言就是下结论,例如ab,正则:a(?=b),匹配a并且向右看是b,得到的结果是a,断言不会在匹配的内容当中,如果是a(?=c),则匹配不到任何内容,因为匹配a以后向右看并不是c。另外,零宽断言分两种:前瞻(Lookahead)和后顾(Lookbehind);但JavaScript只支持前瞻。

// 获取字符串中以ing结尾的单词的前半部分
var str = 'I love dancing but he likes playing';
var pattern = /\b\w+(?=ing\b)/g;
var ans = str.match(pattern);
console.log(ans);
output:
[danc,play]

// 获取第五位不是i的单词的前四位
var s = 'I love dancing but he likes singing';
var pattern = /\b\w{4}(?!i)/g;
var ans = s.match(pattern);
console.log(ans); // ["love", "like"]

下面以一个很经典的例子结束本期

var str = '1234567890'
'12334565632'.replace(/(\d)(?=(\d{3})+$)/g, "$1,");
output:
"12,334,565,632"
记住要加上g,不然结果是12,334565632

又要结束了,下期会给大家带来前端工具gulp的文章。

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

推荐阅读更多精彩内容