美文网首页
正则表达式

正则表达式

作者: 饼干www | 来源:发表于2019-10-28 23:30 被阅读0次

    一、字符组

    1.1

    排除型
    [^0-9] 表示 “0-9之外的字符“^”紧跟“[”表示“除什么什么之外”
    排除型字符组只能排除单个字符

    1.2 字符组简记

    简记 对应字符 说明
    \d [0-9] digit
    \w [0-9a-zA-Z_] word
    \s [\t\r\n\v\f] \t制表符 \r回车符 \n换行符
    \D [^\d] 与\d相反
    \W [^\w] 与\w相反
    \S [^\s] 与\s相反
    [\s\S] [\d\D] [\s\S] 匹配任意字符

    二、量词

    2.1 一般形式

    量词 说明
    {n} 之前的元素必须出现n次
    {m,n} 之前的元素最少出现m次,最多出现n次
    {m,} 最少出现m次,没有上限
    {0,n} 0到n次

    2.2 量词简记法

    常用量词 {m,n}等价方式
    * {0,}
    + {1,}
    {0,1}

    2.3 点号

    点号匹配任意字符,其中\n不能匹配

    2.4 回溯

    "[^"]"主要为了排除"hello world" world"这种情况,
    匹配优先量词
    在拿不定是否要匹配的时候,优先尝试匹配,并且记下这个状态,以备将来后悔。
    " .
    " 在匹配"hello world" second"时,会匹配第一个双引号之后的所有字符,再进行回溯,表达式中的"匹配了字符串的字符",整个匹配宣告完毕。
    ————————————————————
    . 优先匹配,知道匹配最后一个字符,发现都是符合 . 这个状态的。
    开始回溯。
    最后一个字符符合,结束。

    2.5 忽略优先量词

    <script type="text/javascript">
        alert('hello world');
    </script>
    <br/>
    <script type="text/javascript">
        alert("I think you're right");
    </script>
    

    匹配:

    <script type="text/javascript">[/s/S]*</script>
    

    匹配优先量词会优先匹配最后一个字符,这时候已经没有匹配的字符了,但正则表达式中的”</script>“还没有匹配到,所以只能查询之前保存备用的状态,看看能不能回退几步,照顾“</script>”的匹配。查询到最近保存的状态是:【“</script>”也可能是[/s/S]不应该匹配的】。于是让[/s/S]反悔对”</script>“的匹配,所以整个匹配过程宣告成功。
    匹配的结果是:

        alert('hello world');
    </script>
    <br/>
    <script type="text/javascript">
        alert("I think you're right");
    

    这样和我们的预期并不相同。
    我们需要采用忽略优先量词
    如果不确定要匹配,忽略优先量词会选择“不匹配”的状态,再尝试表达式中之后的元素,如果尝试失败,再回溯,选择之前保存的“匹配”的状态。
    也就是,当遇到”<“字符时,[/s/S]选择不匹配,尝试将“</script>”与表达式中的“</script>”比较,比较成功,返回成功的字符串。
    正确的写法是

    <script type="text/javascript">[/s/S]*?</script>
    

    *与*?的区别在于,在实际匹配的过程中,遇到[/s/S]能匹配的字符,先尝试忽略,如果后面的元素不能匹配(即“</script>”),再尝试匹配。直到匹配到第一个出现的“</script>”为止。

    匹配优先量词 和 忽略优先量词相比,匹配优先量词效率更高。

    2.6 转义

    一般量词的转义,例如{m,n},如果希望匹配{m,n},直接加上{m,n}即可
    *? 的转义 是 /*/?

    三、括号

    3.1 分组

    身份证号码
    15位都是数字&首字母不能为0
    18位 前17位是数字&首字母不能为0,末位可能是数字|字母x

    说明 对应字符
    首位是数字,不能为0 [1-9]
    去除首末2位,剩下13位或16位,都是数字 \d{13, 16}
    末位可能是数字,也可能是x [0-9x]

    [1-9]\d{13, 16}[0-9x]
    

    但这样写是不对的,不能匹配。
    我们可以采用括号的方式改变量词的作用元素

    [1-9]\d{14}(\d{2}[0-9x])?
    

    3.2 多选结构

    结构形式为:

    (...|...)
    

    上面的身份证号可以表示为:

    ([1-9]\d{14}|[1-9]\d{16}[0-9x])
    

    匹配0~255之间的数字

    ((00)?[0-9]|0?[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])
    

    手机号

    (0|\+86)?(13[0-9]|15[0-356]|18[025-9])\d{8}
    

    四、断言

    4.1 单词边界

    说明:

    表达式 说明
    \brow\b 只能是单词row
    \brow 例如row、rowdy等
    row\b 例如row、tomorrow等

    用\b\w+\b来匹配一个句子中的单词。

    4.2

    ^ 开始
    $ 结束

    4.3 环视

    名字 记法 判断方向 结构内表达式匹配成功的返回值
    肯定顺序环视 (?=...) 向右 True
    否定顺序环视 (?!...) 向右 False
    肯定逆序环视 (?<=...) 向左 True
    否定逆序环视 (?<!...) 向左 False

    举个例子:
    <(?!/) 表示<右侧不能出现/,它和<[^/]类似,但却不同。
    <(?!/)匹配的仅仅只有<
    <[^/]匹配<及其后面一个字符
    环视最大的特点是“匹配完成之后还停留在原地”

    格式化数字

    (?<=\d)(?=(\d{3})+(?!\d))
    '123456'.replace(/(?<=\d)(?=(\d{3})+(?!\d))/u, ',')
    

    分析:


    字符串可拆分为(?<=\d)和(?=(\d{3})+(?!\d))
    (?<=\d)表示 当前字符左侧必须要出现数字
    (?=(\d{3})+(?!\d))表示字符右侧必须要出现(\d{3})+(?!\d)


    (\d{3})+(?!\d)可拆分
    (\d{3})+表示三个连续数字至少出现1次
    (?!\d)表示右侧必定不能出现数字

    五、匹配模式

    5.1

    表达式 说明
    \regex\i 不区分大小写
    dotALL(点号通配) 单行模式
    \regex\m 多行模式
    \regex\x 注释模式
    \regex\u 表示按unicode(utf-8)匹配(主要针对多字节比如汉字)
    \regex\s 表示将字符串视为单行来匹配

    六、捕获分组的引用

    6.1

    如果要在正则表达式内部引用捕获分组,则应当使用\num记法,其中num为对应捕获分组的编号

    /^([a-z])\1$/u.test("aa") //true
    

    如果要在replacement字符串中引用捕获分组,则应当使用$num记法。

    "2019-10-28".replace(/(\d{4})-(\d{2})-(\d{2})/u, "$2/$3/$1") //10/28/2019
    

    如需表示$符号,必须转义为$$

    "the price is 12.99".replace(/(\d+\.\d{0,2})/u, "$$$1"); //the price is $12.99
    

    6.2 命名分组

    用法:

    (?<name>regex)
    

    栗子:

    pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
    result = pattern.exec("2019-10-30");
    
    结果

    6.3(与6.1对应)

    在正则表达式内部引用捕获分组,应当使用\k<name>记法

    /^(?<char>[a-z])\k<char>$/u.test('aa');
    
    regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
    replacement = "$<month>/$<day>/$<year>"
    "2019-10-30".replace(regex, replacement); //"10/30/2019"
    
    "the price is 12.99".replace(/(?<money>\d+\.\d{0,2})/u, "$$$<money>");
    

    七、

    相关文章

      网友评论

          本文标题:正则表达式

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