美文网首页
#hello,JS:07 正则表达式

#hello,JS:07 正则表达式

作者: 饥人谷_远方 | 来源:发表于2018-08-11 14:03 被阅读0次

    一、意义:

    用来判断用户输入是否符合某些特定规则,如检测判断用户所填信息是否为正确的手机号?正确的邮箱地址?以及在很多文本编辑器中,则更常用来检索、替换那些符合某个模式的文本。

    二、定义:

    JS中的特定对象,用来指定某些规则,对字符串进行匹配,是否符合规则,或者将其结果拿出来检测是否匹配该结果。

    三、如何创建正则表达式

    通过内置对象RegExp去支持正则表达式。如果我们想匹配字符串中<%xxx%>两个百分号分割的字符串可以这么写。创建正则表达式对象有两种方法:

    1、构造函数方法

     var reg=new RegExp('<%[^%>]+%>','g');
    

    注:正则表达式使用new RegExp方法,传递的是字符串,而正则表达式里还有一些参数,表示匹配之后需要遵循什么规则

    2.字面量方法

     var reg=/<%[^%>]%>/g;
    

    注:

    • g:global,全文搜索,不添加的话搜索到第一个结果停止搜索
    • i:ingore case,忽略大小写,默认大小写敏感
    • m:multiple lines,多行搜索

    四、正则表达式如何表达

    var reg = /hello/ig   //可看成reg创建了一个正则表达式的对象
    --> undefined
    reg
    --> /hello/gi   //对象,是控制台对一个对象特有的表达
    //事实上,reg不是一个字符串,而是一个对象,如下
    typeof reg
    -->"object"
    
    //如何表示一个字符串
    var str = '/hello/ig'
    --> undefined
    str
    --> "/hello/ig"
    typeof str
    --> "string"
    

    五、正则表达式的其他概念

    正则表达式让人望而却步的重要原因是转义字符太多,导致组合出来的也非常多
    自我总结:
    正则表达式的匹配字符,在预设的字符串中通过正则的匹配字符进行检索,找出匹配该正则字符符合的参数/元素

    1、元字符

    即正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符

    ( [ { \ ^ $ | ) ? * + .
    

    比如我们返回一个带有元字符的正则表达式,需要:

    var reg = '/\[h\]ello/ig'
    --> undefined
    reg
    --> "/[h]ello/ig"
    

    不是每个元字符都有特定的意义,在不同组合中元字符有不同意义:


    image

    2、字符类 匹配

    正则表达式表示一个字符串,匹配的是一个字符串中相应的字符
    我们可以使用元字符[ ]构建一个简单的类,用来匹配某一类,
    如匹配一个手机号:

    var reg =/[a-z]/ig
    或者
    var reg =/[abc01234]/ig
    //[a-z] 或[0-9]表示一个字符,-  表示一个范围和区间
    

    匹配一个数字(或大小写字母)

    var reg =/[0-A9-c5-Bn-Z]/ig
    

    3、取反 匹配

    var reg =/[^abc01234]/ig
    //^表示只要不是中括号里的参数中的任何一个,则都被选中
    

    4、预定义类 匹配

    即有没有符号代替数字或者非数字?
    如我们希望匹配一个可以是ab+数字+任意字符的字符串,就可以这样写了 /ab\d./

    var reg = /ab\d./
    

    图:


    image

    5、边界 匹配

    (1)区分一下^ 作为取反和边界匹配的差别

    • 如:取反匹配的表示
    //取反:匹配的是除了hello这个字符串之外的所有元素字符串,
    str.match(/[^hello]/g)  
    --> (47) [" ", "w", "r", "d", " ", "1", "2", "3", "4", "5", "6", "7", "8", " ", "   ", " ", "
    ", " ", "j", "i", "r", "n", "g", "u", " ", "↵", " ", "w", "a", "n", "g", "x", "i", "a", "q", "i", "n", " ", "↵", " ", "n", "i", "a", "s", "i", "j", "i"]
    
    • 如:边界匹配的表示
    //边界:匹配的是以hello开头的字符串
    str.match(/^hello/g)
    --> ["hello"]
    
    //即我们会匹配这个hello,不过要通过此来验证该hello是否位于字符串的开头
    

    var str = 'hello world hello 12345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie'
    --> undefined
    str.match(/^hello/g)
    --> ["hello"]
    

    (2)匹配以XXX结尾

    str.match(/hello$/g)
    --> null  //未匹配上
    

    或者

    var str = 'hello1 world hello2 12345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/hello3$/g)
    --> ["hello3"]
    

    或者

    var str = 'hello1 world hello2 12345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/^hello\d/g)
    --> ["hello1"]
    str.match(/hello\d/g)
    --> (3) ["hello1", "hello2", "hello3"]
    

    (3)单词边界 匹配

    var str = 'hello1 world hello2 12345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/\bhello\d\b/g)
    --> (3) ["hello1", "hello2", "hello3"]
    

    或者

    var str = 'hello1 whello9-Ahello5orld hello2 12-hello8-A345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/\bhello\d\b/g)
    --> (4) ["hello1", "hello2", "hello8", "hello3"]  //以此可看出单词边界的一个标准,前后均有空格或者以下情况
    

    或者: - 也为单词边界

    var str = 'hello1 hello9-Ahello5orld hello2 12-hello8-A345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/\bhello\d/g)
    //注:这里右侧少了一个\b的边界匹配,返回如下:
    --> (5) ["hello1", "hello9", "hello2", "hello8", "hello3"]
    

    或者:\t 也为单词边界

    var str = '\thello1 hello9-Ahello5orld hello2 12-hello8-A345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/\bhello\d\b/g)
    -->(5) ["hello1", "hello9", "hello2", "hello8", "hello3"]
    

    \r 也为单词边界

    var str = '\rhello1 hello9-Ahello5orld hello2 12-hello8-A345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/\bhello\d\b/g)
    --> (5) ["hello1", "hello9", "hello2", "hello8", "hello3"]
    

    \n

    var str = '\nhello1 hello9-Ahello5orld hello2 12-hello8-A345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie hello3'
    --> undefined
    str.match(/\bhello\d\b/g)
    --> (5) ["hello1", "hello9", "hello2", "hello8", "hello3"]
    

    如何判断一个字符串中是否有某个单词(元素/参数)?(相当于一个class中是否包含某元素?),假设:

    var str = 'header3 clearfix active header-fixed'
    

    如如何求header这个单词?
    ❌错误解法

    var str = 'header3 clearfix active header-fixed'
    -->undefined
    str.match(/\bheader\b/g)
    --> ["header"]  //系统默认第四个单词中的header
    

    ✅正确解法:
    | 可以匹配空白字符 本身也可以作为开头

    var str = 'header3 clearfix active header-fixed'
    -->undefined
    str.match(/(^|\s)header($|\s)/g)
    --> null  //没有匹配到任何东西
    var str = 'header3 clearfix active header-fixed header'
    undefined
    str.match(/(^|\s)header($|\s)/g)
    --> [" header"]  //从上一步,知道匹配到最后一个单词header
    

    6、量词 匹配

    image

    看一个字符串是否为url,该如何匹配

    var str = 'http://wangxiaoqin.com'
    --> undefined
    var str2 = 'https://wangxiaoqin.com'
    -->undefined
    str.match(/https?:\/\/.+/g) //s 这个字母后加 ? 表示出现零次或一次(最多出现一次)不管有没有出现都行
                              //.  任意字符   +  多次
    --> ["http://wangxiaoqin.com"]
    str2.match(/https?:\/\/.+/g)
    --> ["https://wangxiaoqin.com"]
    
    //s出现多次,?无效   *有效  其他匹配字符
    var str3 = 'httpssssss://wangxiaoqin.com'
    --> undefined
    str3.match(/https?:\/\/.+/g)
    --> null
    str3.match(/https*:\/\/.+/g)
    --> ["httpssssss://wangxiaoqin.com"]
    

    7、实践

    (1)实践1:如何更精准地判断url?
    固定元素 http:// https:// //

    str.match(/^(https?:)?\/\/.+/)   //(https?:)? ()里的表示可有可无
    --> (2) ["http://wangxiaoqin.com", "http:", index: 0, input: "http://wangxiaoqin.com", groups: undefined]
    str2.match(/^(https?:)?\/\/.+/)
    --> (2) ["https://wangxiaoqin.com", "https:", index: 0, input: "https://wangxiaoqin.com", groups: undefined]
    var str4 = '//wangxiaoqin.com'
    --> undefined
    str4.match(/^(https?:)?\/\/.+/)
    --> (2) ["//wangxiaoqin.com", undefined, index: 0, input: "//wangxiaoqin.com", groups: undefined]
    

    (2)实践2:如何判断用户的输入是手机号?
    假设:

    var str1 ='15011112222'
    -->undefined
    var str2 ='aaadd15011112222'
    --> undefined
    var str3 ='150111111222222555555'
    --> undefined
    var str4 ='150aaadd11112222'
    --> undefined
    

    分析:手机号只有11位、数字开头/结尾、 中国手机号以1开头

    //接上面代码继续
    str1.match(/1[3578]\d{9}/g)
    --> ["15011112222"]  // ✅准确无误地完全匹配上
    str2.match(/1[3578]\d{9}/g)
    --> ["15011112222"]   //虽然也返回正则所规定的,但只是部分匹配
    

    如何接解决?分析:手机号前后都没东西,也就是要以数字1作为开头,结尾也要匹配数字字符

    //接上面代码
    str2.match(/^1[3578]\d{9}/g)
    --> null
    str1.match(/^1[3578]\d{9}/g)
    -->["15011112222"]   ✅
    str3.match(/^1[3578]\d{9}/g)
    --> ["15011111122"]   //虽然也返回正则所规定的,也是以1为开头的,但没有结尾
    
    //$ 结尾匹配上该字符
    str1.match(/^1[3578]\d{9}$/g)
    --> ["15011112222"]
    str2.match(/^1[3578]\d{9}$/g)
    --> null
    str3.match(/^1[3578]\d{9}$/g)
    --> null
    str4.match(/^1[3578]\d{9}$/g)
    --> null
    

    图:


    image

    8、如何具象使用正则?

    (1)先利用字符串的搜索去把正则给应用起来

    var str = 'hello world 12345678 \t \r jirengu \n wangxiaoqin \n nihaoshijie'
    --> undefined
    

    结果如:


    image

    (2)接着回忆,利用字符串的搜索功能搜出某个字的起始下标(所传递的是一个字符串)

    str.search('world') 
    --> 6  //这里可看出str输出的字符串,空格跳过
    

    这里,可以使用正则表达式进行检索

    str.match('world')
    str.match(/\d/)
    //只匹配到一次,1,拿到就结束
    

    如图:


    image
    //匹配所有的数字字符
    str.match(/\d/g)
    -->(8) ["1", "2", "3", "4", "5", "6", "7", "8"]
    

    如图:


    image

    六、贪婪模式与非贪婪模式

    1、贪婪模式:

    在贪婪(默认)模式下,正则引擎【尽可能多】地重复匹配字符
    先看这个代码:

    var str = 'a "witch" and her "boom" is one'
    --> undefined
    str.match(/".*"/g)
    --> [""witch" and her "boom""]
    

    按照我们的逻辑来看,本来我们想要匹配的是"witch"和"boom"两个字符串,但是结果却出乎我们的意料,是"witch" and her "boom"这样一个整体的字符串。这样的字符串则是因为正则表达式的贪婪模式起的效果。
    正则引擎演示如下:
    正则的贪婪模式采用了查找算法的形式进行检索匹配字符。正则引擎从字符串的第0位开始检索:(在此为若愚老师打call,他讲正则引擎工作讲得真的很不错😂)


    image

    2、非贪婪模式:

    与贪婪模式相反,可通过在代表数量的标示符后放置 ?(表示尽可能地少匹配) 来开启非贪婪模式。如:? 、 +?甚至是??
    非贪婪模式下,正则引擎尽可能少地重复匹配字符
    演示如下:

    var str = 'a "witch" and her "boom" is one'
    --> undefined
    str.match(/".*?"/g)   
    --> (2) [""witch"", ""boom""]
    

    图:


    image

    七、分组

    使用量词的时候匹配多个字符,而不是像上面例子只是匹配一个
    首先,假设写成 hunger{10} 的话匹配的是hunge+r出现10次

    /hunger{10}/   //hunge+r出现10次
    

    把hunger作为一个整体呢?使用()就可以达到此目的,我们称为分组

    /(hugner){10}/
    

    字符或 | 在正则引擎中是怎么处理的呢

    var str = 'helloworld'
    --> undefined
    str.match(/hello|sworld/) \ //有个疑问,是(hello)|(sworld),还是hell(o|s)world
                  //匹配返回的有可能是hello或者hells
    -->["hello", index: 0, input: "helloworld", groups: undefined]
    验证之后,等同于
    str.match(/(hello)|(sworld)/)
    --> (3) ["hello", "hello", undefined, index: 0, input: "helloworld", groups: undefined]
    str.match(/hello|sworld/g)
    --> ["hello"]
    
    //而事实上,匹配helloworld这个字符串,字符 |  则需要将左右两边相邻的字母用()包裹起来
     str.match(/hell(o|s)world/g)
    --> ["helloworld"]
    

    所以

    (hello|world){20}  //表示hello或者world都匹配出现20次 
    

    分组的作用

    str
    --> "helloworld"
    str.match(/(he)l(lo)/)
    --> (3) ["hello", "he", "lo", index: 0, input: "helloworld", groups: undefined]
    VS
    str.match(/hello/)
    -->["hello", index: 0, input: "helloworld", groups: undefined]
    

    分组的价值实践:(同时运用了非贪婪模式的 ?让返回完全匹配 )

    var str ='<a href="http://wangxiaoqin.com">'
    --> undefined
    str.match(/href="(https?:\/\/.+?)"/)
    --> (2) ["href="http://wangxiaoqin.com"", "http://wangxiaoqin.com", index: 3, input: "<a href="http://wangxiaoqin.com">", groups: undefined]
    str.match(/href="(https?:\/\/.+?)"/)[1]
    -->"http://wangxiaoqin.com"
    

    非贪婪模式 VS贪婪模式

    var str ='<a href="http://wangxiaoqin.com">"hello"'
    --> undefined
    str.match(/href="(https?:\/\/.+?)"/)
    --> (2) ["href="http://wangxiaoqin.com"", "http://wangxiaoqin.com", index: 3, input: "<a href="http://wangxiaoqin.com">"hello"", groups: undefined]
    str.match(/href="(https?:\/\/.+?)"/g)
    --> ["href="http://wangxiaoqin.com""]
    
    str.match(/href="(https?:\/\/.+)"/)
    --> (2) ["href="http://wangxiaoqin.com">"hello"", "http://wangxiaoqin.com">"hello", index: 3, input: "<a href="http://wangxiaoqin.com">"hello"", groups: undefined]
    str.match(/href="(https?:\/\/.+)"/g)
    --> ["href="http://wangxiaoqin.com">"hello""]
    

    八、前瞻

    var str=hunger(?=Byron)
    
    str.exec('goodByron123'); //['good']
    str.exec('goodCasper123'); //null
    str.exec('goodCasper123');//null
    

    九、正则表达式的相关用法

    1、reg.test(str)

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

    var reg = /\d+\.\d{1,2}$/g;
    
    reg.test('123.45'); //true
    reg.test('0.2'); //true
    reg.test('a.34'); //false
    reg.test('34.5678'); //false
    

    实践价值:
    测试一个手机号是否存在?

    var reg = /^1[3578]\d{9}$/g   //正则的手机号检索标准
    --> undefined
    reg.test('18320158956')
    --> true
    

    2、reg.exec(str)

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

    var str ='123 456 789'
    var reg =/\d{3}/   //未添加g,则匹配一次就结束
    reg.exec(str)
    ["123", index: 0, input: "123 456 789", groups: undefined]
    
    /* 进行g的全局匹配 */
    var str ='123 456 789'
    var reg =/\d{3}/g
    reg.exec(str)
    --> ["123", index: 0, input: "123 456 789", groups: undefined]
    reg.exec(str)
    --> ["456", index: 4, input: "123 456 789", groups: undefined]
    reg.exec(str)
    --> ["789", index: 8, input: "123 456 789", groups: undefined]
    

    实践价值:
    如找出相对应的邮箱,手机号码等

    //代码如下:  
      var str ='123 456 789'
      var reg =/\d{3}/g
    while(result=reg.exec(str)){
             console.log(result[0])
    }
    
    --> 123
        456
        789
    

    3、str.split(reg)

    使用split方法把字符串分割为字符数组

    var str = 'h   e  llo wan g xi ao qi   n'
    undefined
    //以前
    str.split('')
    --> (29) ["h", " ", " ", " ", "e", " ", " ", "l", "l", "o", " ", "w", "a", "n", " ", "g", " ", "x", "i", " ", "a", "o", " ", "q", "i", " ", " ", " ", "n"]
    str.split(' ')
    --> (14) ["h", "", "", "e", "", "llo", "wan", "g", "xi", "ao", "qi", "", "", "n"]
    //现在:用正则表达式做一个检索分类
    str.split(/\s/)
    --> (14) ["h", "", "", "e", "", "llo", "wan", "g", "xi", "ao", "qi", "", "", "n"]
    str.split(/\s*/)
    --> (16) ["h", "e", "l", "l", "o", "w", "a", "n", "g", "x", "i", "a", "o", "q", "i", "n"]
    

    相关文章

      网友评论

          本文标题:#hello,JS:07 正则表达式

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