正则

一直使用正则但是一直没有能够把正则的基本书完整的看完,所以边学边看吧。当然对于这些技术,最好还是能够有一个非常系统完整的学习。争取后面能把《正则指引》看完。
说明:本文任何函数解释和分析都以W3C JS Reg文档解释为准,本人技术粗浅,有可能有理解不到位的地方,文章当日后发现理解错误会持续更新)

正则基础参考文档

非常推荐这一篇网上最好的正则快速入门教程+手册,30分钟正则系列
此外,遇到具体的问题和一些方法函数请参考W3C JS Reg文档

JS正则基础

JS正则定义

本文的RegExp采用直接量语法表示:/pattern/attributes。attributes有三个选择,i、m和g,m(多行匹配)不常用直接省略,所以一个pattern(匹配模式)可以表示如下:

var pattern = /hello/ig;
i(ignore)表示不区分大小写(地搜索匹配),比较简单,以下例子中不加述说;g(global)表示全局(搜索匹配),即找到一个后继续找下去,相对复杂,以下各种方法中会特别介绍。

还有一种是使用

var re = new RegExp();//RegExp是一个对象,和Aarray一样
//但这样没有任何效果,需要将正则表达式的内容作为字符串传递进去
re =new RegExp("a");//最简单的正则表达式,将匹配字母a
re=new RegExp("a","i");//第二个参数,表示匹配时不分大小写

** 注意 ** : 使用RegExp类的方式创建的正则对象中需要双重转义,如正则中输入'',本身必须转义为'\',但是在这个对象中创建字符串必须为'\\','\'为转义的最终出现在正则中的'',总之很麻烦,而且定义的写法也很啰嗦,所以直接用所谓的量语法来定义就好/(your reg)/写起来真的很简单,随写随用就好啊。

JS正则RegExp对象

RegExp 对象方法
  • test -- RegExp的test方法用来测试字符串是否匹配给出的匹配模式,返回布尔值,检测指定字符串是否含有某个子串(或者匹配模式),返回true或者false。
  • exec -- RegExp的exec方法返回包含第一个匹配的的数组或null
  • compile,把正则表达式编译为内部格式,从而执行得更快(我没怎么用过,具体需要再研究下这个优化的效果),但是可以想象,在复杂多次正则匹配的情况下,这应该是一个优化的好路子
RegExp 对象属性
  • global -- 布尔值,若全局选项g已设置则返回true,否则返回false;(即/g)
  • ignoreCase -- 布尔值,若忽略大小写选项i已设置则返回true,否则返回false;(即/i)
  • lastIndex -- 整数,使用exec或test方法时被填入,表示下次匹配将会从哪个字符位置开始(根据说明,应该是只有在使用g全局正则的时候这个值才会被修改,否则应该永远是第一个位置才对,* 没有代码实践过,有待进一步研究 *)
  • multiline -- 布尔值,表示多行模式选项m是否设置,若设置则返回true,否则返回false(即/m,* 多行模式需要进一步研究用法 *)
  • source -- 正则表达式的元字符串形式。/\/的source将返回'\'。

JS正则String对象

由于正则天生的好基友就是String,所以必须有通过string来搞正则的路子

String 对象方法
  • search -- 检索与正则表达式相匹配的值。搜索指定字符串中是否含有某子串(或者匹配模式),如有,返回子串在原串中的初始位置,如没有,返回-1。
  • match -- 找到一个或多个正则表达式的匹配。
  • replace -- 替换与正则表达式匹配的子串。用另一个子串替换指定字符串中的某子串(或者匹配模式),返回替换后的新的字符串 str.replace(‘搜索模式’,'替换的内容’) 如果用的是pattern并且带g,则全部替换;否则替换第一处。

如果需要替代的内容不是指定的字符串,而是跟匹配模式或者原字符串有关,那么就要用到$了(** 记住这些和$符号有关的东东只和replace有关哦 **)。

  • $1、$2、...、$99 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
  • $& 与 regexp 相匹配的子串。
  • $` 位于匹配子串左侧的文本。
  • $' 位于匹配子串右侧的文本。
  • $$ 直接量符号。

Sample Code

     name = "Doe, John";
     name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1");
  • split -- 把字符串分割为字符串数组。

那么问题来了

RegExp和String都好用,那么我应该用谁呢?谁更好?又有什么区别么?

关于使用情景
  1. 由于RegExp自带compile方法,那么很明显需要** 优化性能 **那么你最好的选择必然是RegExp
  2. 其他的,反正由于无论用哪个传入的都是RegExp对象,那么没有必然的谁更好,一定要用谁,那么怎么用就取决于这些方法的区别
<a href="#diff">String和RegExp比较</a>
  • 关于test和search:search不仅能反馈是否匹配上,而且能够返回位置,test只能返回是否匹配上
  • 关于exec和match:这两个比较复杂点,坑比较深,** 非常重要!!! **

match是exec的轻量版,当不使用全局模式匹配时,match和exec返回结果一致;当使用全局模式匹配时,match直接返回一个字符串数组,获得的信息远没有exec多,但是使用方式简单。

以上引用自我所认识的JavaScript正则表达式文章
好那么我们继续延生我们的思考,并进行一些实验,比较这两个函数是最实用也是用的最多的解决最多问题的

"abc1 bcd2 cde3".match(/(\w+)(\d+)/)

result:

result = ["abc1", "abc", "1"]

分析,这里result[0]表示的是match的匹配的string
result[1]表示的是match中regexp的第一个分组匹配结果
result[2]表示的是match的第二个分组匹配的结果

/(\w+)(\d+)/.exec("abc1 bcd2 cde3")

result:

result =  ["abc1", "abc", "1"]

看来果然和match是一样的
Go On!

"abc1 bcd2 cde3".match(/(\w+)(\d+)/g)

result:

result = ["abc1", "bcd2", "cde3"]

加了g之后的match的结果数组已经不包括了分组的相关信息了,每一个结果中的元素都是匹配的string

Paste_Image.png

将此结果和下面的exec做对比

/(\w+)(\d+)/g.exec("abc1 bcd2 cde3")

result:

result = ["abc1", "abc", "1"]

加了g之后的exec还是无动于衷,还是和之前一样,只是匹配并返回了第一个string,但是仍然包含了所有的分组的匹配
然后根据一些资料,在g下,exec会修改上文所述的RegExp的lastIndex值,从而当下一次exec执行时,会接着上一次的lastIndex来继续匹配.但是本例中所使用的是/(\w+)(\d+)/g 常量,所以对象lastIndex的值永远都是0

Paste_Image.png

这里demo了使用pattern变量的方式,其中index 和input是这个array的属性

总结:如果你只是需要获取所有匹配的string那么match是最好的选择,如果你有更高更复杂的需求,使用exec,并且使用g来不断执行exec获取每一个匹配string和该次匹配的分组的匹配结果才是最强大和完美的用法

参考文献
30分钟正则系列
W3C JS Reg文档
我所认识的JavaScript正则表达式

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

推荐阅读更多精彩内容