一直使用正则但是一直没有能够把正则的基本书完整的看完,所以边学边看吧。当然对于这些技术,最好还是能够有一个非常系统完整的学习。争取后面能把《正则指引》看完。
(说明:本文任何函数解释和分析都以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都好用,那么我应该用谁呢?谁更好?又有什么区别么?
关于使用情景
- 由于RegExp自带compile方法,那么很明显需要** 优化性能 **那么你最好的选择必然是RegExp
- 其他的,反正由于无论用哪个传入的都是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
这里demo了使用pattern变量的方式,其中index 和input是这个array的属性
总结:如果你只是需要获取所有匹配的string那么match是最好的选择,如果你有更高更复杂的需求,使用exec,并且使用g来不断执行exec获取每一个匹配string和该次匹配的分组的匹配结果才是最强大和完美的用法
网友评论