美文网首页
正则表达式学习笔记

正则表达式学习笔记

作者: 灯不梨喵 | 来源:发表于2017-11-19 22:10 被阅读0次

    正则表达式的语法不再多说

    正则RegExp类型有几个常用方法:

    exec()

    该方法是专门为捕获组而设计的。

    例:

    var text='I love cat and dog and panda';

    var pattern=/I love cat( and dog( and panda)?)?/gi;

    var matches=pattern.exec(text);

    console.log(matches.input)//I love cat and dog and panda

    console.log(matches.index)//0

    console.log(matches)//[ 'I love cat and dog and panda',

    ' and dog and panda',

    ' and panda',

    index: 0,

    input: 'I love cat and dog and panda' ]

    从例子中应该可以隐约体会到捕获组的意思。

    我在学习正则表达式的时候,遇到的难点之一就是捕获组和非捕获组。

    捕获组就是满足子表达式(就是被括号包含的表达式)的内容。它们是有编号的,方便以后引用。(无论是在正则表达式内外都可以引用)

    注意,编号为0的捕获组,指的是符合正则表达式整体的内容。

    引用方法是 "/" 加上一个数字。"/1" 引用第1对括号内匹配到的字符串。

    那编号是怎么编呢?不然怎么知道引用哪个呢?编号根据左括号的顺序而定。

    举个🌰

    var text2='meowmeowmeowmeow'

    var ptn=/(meow)\1/

    var m=ptn.exec(text2);

    console.log(m)//[ 'meowmeow', 'meow', index: 0, input: 'meowmeowmeowmeow' ]

    看到了吧,\1表示第一个子表达式匹配的内容,所以输出的结果是两个meow。

    还有另外一个🌰

    var text='I love cat and dog and panda';

    var pattern=/I love cat( and dog( and panda)?)?/gi;

    var result=text.replace(pattern,'I love kitties and puppies$2')

    console.log(result)//I love kitties and puppies and panda

    但是有时候数字很不直观,大家知道正则表达式解读起来有时候麻烦,如果复杂过头,写的人自己都不知道写的什么鬼,那怎么办?可不可以自己命名啊?可以(任性

    捕获组分为普通捕获组和命名捕获组。

    普通捕获组就是刚才介绍的,只用数字编号;而命名捕获组,除了数字编号以外,可以自定义一个捕获组的名字。不过js貌似还不支持命名捕获组(溜了溜了

    还有一个鬼登西叫做非捕获组,顾名思义就是我看到你了,但是我不会抓住你,找到你以后就放生你,所以非捕获组是不能引用的。

    以下是常用的一些非捕获组

    ?:pattern 匹配pattern但不获取结果

    ?=pattern正向预查 比方说p1(?=p2),满足该表达式的内容为后面紧跟着p2的p1

    ?!pattern反向预查 后面不跟着p2的p1

    而类似?<=的后瞻表达式,js也不支持,嘻嘻(再次溜

    🌰🌰🌰🌰🌰🌰时间

    尝试一下正向预查🌰:

    var text2='Windows 95 and Windows 98 and Windows xp'

    var ptn=/Windows(?= [\d]+\b)/g;

    console.log(text2.replace(ptn,'meow'));//meow 95 and meow 98 and Windows xp

    在看看反向预查🌰:

    var text2='Windows 95 and Windows 98 and Windows xp'

    var ptn=/Windows(?! [\d]+\b)/g;

    console.log(text2.replace(ptn,'meow'));//Windows 95 and Windows 98 and meow xp

    test()

    如果文本有内容匹配正则表达式,返回true,否则返回false

    构造函数的属性

    摘抄了一下别人的博客,毕竟照着书手打很麻烦

    input (简写为$_) 最近一次要匹配的字符串。

    lastMatch(简写$&) 最近一次的匹配项

    lastParen(简写$+) 最近一次匹配的捕获组。

    leftContext(简写$`) input字符串中lastMatch之前的文本

    rightContext(简写$') input字符串中lastMatch之后的文本

    multiline(简写$*) 布尔值,表示是否所有表达式都使用多行模式。

    在进行exec或者test操作以后,可从RegExp对象中提取上述信息

    🌰🌰🌰🌰🌰🌰

    var text='I love cat and dog and panda';

    var pattern=/I love cat( and dog( and panda)?)?/gi;

    var matches=pattern.test(text);

    console.log(RegExp.input)//I love cat and dog and panda

    console.log(RegExp.$_)//I love cat and dog and panda

    console.log(RegExp["$_"])//I love cat and dog and panda

    match()

    返回符合正则表达式的内容(数组),未匹配返回null

    🌰

    var text2='Windows 95 and Windows 98 and Windows xp'

    var ptn=/Windows(?: [\d]+\b)/g;

    console.log(text2.match(ptn))//[ 'Windows 95', 'Windows 98' ]

    search()

    返回匹配到的位置索引,或者在失败时返回-1。

    🌰

    var text3='abcedefe';

    var ptn3=/e/g;

    var res=text3.search(ptn3);

    console.log(res)//3

    var res2=text3.search('/h/g');

    console.log(res2)//-1

    replace()

    刚才讲解的捕获组中,🌰使用了replace方法。

    text.replace(reg,替换的内容)

    split()

    var text3='abcedefe';

    var ptn3=/e/;

    var res=text3.split(ptn3);

    console.log(res)//[ 'abc', 'd', 'f', '' ]

    有一点特别魔幻,当时没有仔细看MDN,以为自己忽略了子表达式有什么其它的作用。

    其实MDN写得一清二楚……

    如果separator包含捕获括号(capturing parentheses),则其匹配结果将会包含在返回的数组中。

    varmyString="Hello 1 word. Sentence number 2.";

    varsplits=myString.split(/(\d)/);

    console.log(splits)//[ 'Hello ', '1', ' word. Sentence number ', '2', '.' ]

    当时自己写了一遍,想了想不对呀,split平时不是这个意思呀……

    正则加不加括号不都一个意思吗……

    下楼拿了个外卖,思考了10分钟,然后再看一遍MDN,呵呵。

    嗯就死记硬背得了。反正这个函数任性么。

    贪婪模式和懒惰模式

    超级难点

    添加修饰匹配次数的量词,默认为贪婪模式,尽可能多地匹配,如* + ?

    而懒惰模式,是在修饰匹配次数的特殊符号后再加上一个 "?" 号,则可以使匹配次数不定的表达式尽可能少的匹配。

    贪婪模式的原理:某个字符串str,使用贪婪模式的正则,首先它会从整个字符串开始观察是否符合正则,若不符合,从字符串结尾逐个减去字符,再次检测,以此类推,直到找到符合规则的字符串为止。

    而懒惰模式则相反,它从字符串开头逐个添加再检索。

    划考点:过滤html标签

    思路:

    标签是成对的,所以可以在后向引用获取;√

    判断标签用〈、 〉符号判定,使用贪婪模式,可以解决其它嵌套标签;√

    如果标签相同,比如

    1.<div><div></div></div>,如果希望获取整个div,使用贪婪模式

    2.<div></div><div></div>,如果希望获取前一个div,使用懒惰模式

    要适当使用贪婪模式或者懒惰模式

    最后用一道题检测下学习成果:

    使用正则表达式实现数字添加千分位

    例10000000000会变成10,000,000,000

    大神解答专栏在此

    大神在专栏里面已经讲的非常清楚。

    文章首先阐明了位置的定义。

    正则表达式里面,\b表示一个边界,表示\w与\W、^、$之间的位置。

    之前一直认为边界符只是一个用来匹配位置的标记,并没有太大的作用,从来没有想过边界替换,所以好像也对这道题无从下手。

    明确了位置的定义后,我们可以想象,千分位的添加,实质上就是每三个数字前面的位置添加一个逗号,而不必使用循环和各种判定条件。(我曾想过用split实现来着...)

    那么要怎么表示\w之间的边界呢?需要对\b进行非操作吗?

    在前面我介绍过正向预查,事实上正向预查可以表示特定的边界,因为可以看作它判定了预查对象前面的表达式+预查对象前面的位置。

    现在刚学正则表达式,还不太熟练,我们一步步,一个个元字符和子表达式添加上去,练习自己对正则表达式的解读。

    var s ="3102546864";

    首先照着概念,我们希望取每3个数字的前面的边界

    var re1=/(?=\d{3})/g;//结果: ,3,1,0,2,5,4,6,864 

    从开头判定,开头后面的确跟着3个数字310,于是开头的位置放置一个逗号;再右移,数字3的后面跟着3个数字102,于是3和102之间放置一个逗号……以此类推,直到864是最后一组3个数字。

    var re2=/(?=(\d{3})+)/g;

    把三个数字看作一个整体,设定为一个子模式,该子模式出现1次或以上时匹配成功。然而结果并没有改变,因为在replace中,+号是可有可无的。

    接下来应该加什么限定条件,才可以令数字呈现3个一组,且不重复?是了,3个一组的数字是从字符串末尾开始计算的,那么加上一个结尾符如何?

    var re3=/(?=(\d{3})+$)/g;//结果: 3,102,546,864

    这个正则表达式的意思是寻找一个位置,该位置往后是1-n组,3个为一组的数字,且这些数字刚好截至到字符串的结尾(即找到数字的个数可以被3整除的一段了)

    还有疑问吗?我们把具有迷惑性的g符去掉看看

    var re4=/(?=(\d{3})+$)/;//结果: 3,102546864,可以知道确实是从目标位置开始界定了。刚才还在困惑正则表达式不是从前往后找吗,怎么倒可以从结尾数着3个一组?现在没有疑问了吧。

    那么reg3的结果似乎已经OK了,是这样吗?如果数字的数量是3的倍数呢?

    var s ="310254686";//结果却是 ,310,254,686 

    位置的概念涵盖了开始位和结束位,现在我们要把开始位排除掉。

    两个方法,一个是(?!^),另一个是\B

    var regexp1=/\B(?=(\d{3})+$)/g;

    var regexp12=/(?!^)(?=(\d{3})+$)/g;

    最后就是 s.replace(regexp1,','),耶

    这里可以测试正则表达式,超级棒

    相关文章

      网友评论

          本文标题:正则表达式学习笔记

          本文链接:https://www.haomeiwen.com/subject/fukpvxtx.html