zoukankan      html  css  js  c++  java
  • JavaScript中的正则表达式

    抄自:https://www.jianshu.com/p/488d60349325

    一、正则声明方式

    1. 构造函数方式

    var reg = new RegExp('d', 'gi');

    通过 new 构造一个正则表达式对象,其中第一个参数 'd' 是正则内容,第二个参数 'gi' 是修饰符。两个参数皆为字符串类型:

    (1) 修饰符的作用是对匹配过程进行限定

    (2) 修饰符有三种:i, g, m,可以同时出现,没有顺序(即 gi 与 ig 一样)

    • i:忽略大小写匹配
    • 全局匹配,即是匹配一个后继续匹配,直到结束
    • 多行匹配,即是遇到换行后不停止匹配,直到结束

    2. 字面量方式

    这种方式很常见。

    var reg = /d/gi;

    两个斜线内为正则的内容,后面可以跟修饰符,与第一种构造函数方式相比更简洁,缺点是正则内容不能拼接,对于大多数场景来说足够了。

    二、正则相关符号

    1. 方括号 [] 用法

    用于查找方括号内的任意字符。

    (1) ^ 在 [] 内开始位置及正则双斜线开始位置有特殊含义,其他位置表示 ^ 字符本身。

    • 正则开头位置表示以某某开头的字符串,如下表示以大写或小写字母开头的且连续为字母的字符串
    'adobe 2016'.match(/^[a-zA-Z]+/);
    // ["adobe"]
    •  在正则 或 匹配中(即 | 匹配),表示 或者以某某字符开始的字符串,如下表示匹配 连续数字 或 以小写字母开头且连续为小写字母的字符串,所以返回结果包含2016 和 adobe,注意返回结果不是 ["2016", "adobe"]
    'adobe2016ps'.match(/d+|^[a-z]+/g);
    // ["adobe", "2016"]
    • 在 [] 内开始位置时,表示不匹配 [] 内除 ^ 以外的所有字符:
    'adobe'.match(/[^abc]/g);
    // ["d", "o", "e"]

    注: $ 与 ^ 的前两个用法相似,只不过匹配的是以某某字符结尾的字符串,举例:

    'adobe 2016'.match(/d+|[a-z]+$/g);
    // ["2016"]
    'adobe'.match(/d+|[a-z]+$/g);
    // ["adobe"]

    (2) - (连字符)表示左边字符的 ASCII 值到右边字符 ASCII 编码值之间及左右字符自身的所有字符

    'adobe PS 2016'.match(/[a-g]/g);
    // ["a", "d", "b", "e"]

    (3) - 连字符左侧的字符对应的 ASCII 值一定要小于或等于右侧的字符,否则会报语法错误

    'adobe'.match(/[z-a]/);
    // Uncaught SyntaxError: Invalid regular expression: /[z-a]/: Range out of order in character class...

    (4) 如果希望对连字符 - 本身进行匹配,需要用反斜线转义

    'adobe-2016'.match(/[a-g-]/g);
    // ["a", "d", "b", "e", "-"]

    (5) 查看 ASCII 表就会发现,大写字母的 ASCII 值是小于小写字母的,因此下面用法会报语法错误

    'adobe-2016'.match(/[a-Z]/g);
    // Uncaught SyntaxError: Invalid regular expression: /[a-Z]/: Range out of order in character ...

    那么问题来了,如果要表示所有字母,不区分大小写怎么办呢?其实有两种方式:

    • 第一种是使用修饰符 i,前面提到过。举例:
    'adobe-PS'.match(/[a-z]/gi);
    // ["a", "d", "o", "b", "e", "P", "S"]
    • 第二种是在正则中明确指明大小写字母,举例:
    'adobe-PS'.match(/[a-zA-Z]/g);
    // ["a", "d", "o", "b", "e", "P", "S"]

    返回结果跟第一种一样。当然这个例子有些特殊:匹配了所有大小写字母。当只匹配部分大小写字母的时候只能使用第二种方式。

    (6) 匹配大小字母不能写成 [A-z],虽然不会报语法错误,但隐式的放大了匹配范围,查看 ASCII 会发现,在大写字母 Z 到小写字母 a 之间还有 [、 、 ]、 ^、 _、 ` 这6个字符,因此不能这么写。

    (7) 有同学会问, w 不也可以匹配字母么?是的,w 确实可以匹配字母,但跟上面说的一样,也隐式的放大了匹配范围,w 除了匹配大小字母外还匹配了数字和下划线,即 w 与 [A-Za-z0-9_] 等价,当然 A-Z、a-z、0-9(等价于d)、_这四组没顺序之分。
    2. 特殊含义字符
    • 匹配任意单个字符,除换行和结束符
    '1+0.2*2=1.4'.match(/.{2}/g);
    // ["1+", "0.", "2*", "2=", "1."]
    • w 匹配任意单词字符(数字、字母、下划线),等价于[A-Za-z0-9_]
    'ad34~!@$ps'.match(/w/g);
    // ["a", "d", "3", "4", "p", "s"]
    • W 匹配任意单词字符,与w相反,等价于[^A-Za-z0-9_]
    'ad34~!@$ps'.match(/W/g);
    // ["~", "!", "@", "$"]
    • d 匹配数字,等价于 [0-9]
    'ps6'.match(/d/g);
    // ["6"]
    • D 匹配非数字,等价于 [^0-9]
    'ps6'.match(/D/g);
    // ["p", "s"]
    • s 匹配空白字符,主要有( 、f、 、 、v),注意'asb'中的s依然是字符s,所以'asb'.match(/s/g)返回 null
    'adobe ps'.match(/s/g);
    // [" "]
    • S 匹配非空白字符,与s相反
    'adobe ps'.match(/S/g);
    // ["a", "d", "o", "b", "e", "p", "s"]
    •  匹配单词边界,注意连续的数字、字母或下划线组成的字符串会认为一个单词
    'adobe(2016) ps6.4'.match(/(w+)/g);
    // ["adobe", "2016", "ps6", "4"]
    • B 匹配非单词边界,仔细体会下面的示例与的结果
    'adobe(2016) ps6.4'.match(/B(w+)/g);
    // ["dobe", "016", "s6"]
    • 匹配NUL字符
    ''.match(//);
    // ["NUL"]
    • 匹配换行符(编码:10,newline)
    'adobe
    ps'.match(/
    /).index;
    • f 匹配换页符
    'adobefps'.match(/f/).index;
    • 匹配回车符(编码:13,return)
    'adobe
    ps'.match(/
    /).index;
    • 匹配制表符,键盘tab对应的字符
    'adobe	ps'.match(/	/).index;
    • v 匹配垂直制表符
    'adobevps'.match(/v/).index;
    • xxx 匹配以八进制数xxx规定的字符
    'a'.charCodeAt(0).toString(8);
    // "141"
    'adobe ps'.match(/141/g);
    // ["a"]
    • xdd 匹配以十六进制数dd规定的字符
    'a'.charCodeAt(0).toString(16);
    // "61"
    'adobe ps'.match(/x61/g);
    // ["a"]
    • uxxxx 匹配以十六进制数xxxx规定的 Unicode字符,注意位数不够需要补0
    'a'.charCodeAt(0).toString(16);
    // "61"
    'adobe ps'.match(/u0061/g);
    // ["a"]

    注意:window系统回车换行符为 ,linux系统下没有 ,linux系统通过vi编辑器打开window系统的文本文件时候,经常在行尾出现^M符号,也就是 的原因,解析文本的时候需要注意相关判断。

    3. 量词说明

    • n+ 匹配包含至少一个n的字符串
    'adobe paas'.match(/a+w+/g);
    // ["adobe", "aas"]
    • n* 匹配包含零个或多个n的字符串
    'ab3 aa12bb'.match(/a*d+/g);
    // ["3", "aa12"]
    • n? 匹配包含零个或一个n的字符串
    'ab3 aa12bb'.match(/a?d+/g);
    // ["3", "a12"]
    • n{x} 匹配包含连续x个n的字符串
    'ab3 aa12bb aaa34'.match(/a{2}d+/g);
    // ["aa12", "aa34"]
    • n{x,y} 匹配包含至少连续x个且最多连续y个n的字符串
    'a3 aaa12bb aaaaaaa34'.match(/a{2,4}d+/g);
    // ["aaa12", "aaaa34"]
    •  n{x,} 匹配包含至少连续x个n的字符串
    'a3 aaa12bbaa4'.match(/a{2,}d+/g);
    // ["aaa12", "aa4"]

    由上可知,以下 表达式1 与 表达式2 等价:

    n+ n{1,}
    n* n{0,}
    n? n{0,1}

    4. 符号说明

    符号 {}、、$、*、+、?、[]、[]、- 已经在前面介绍过,接下来看下其他特殊字符

    • a|b 匹配包含a或b的字符串
    'adobe ps13'.match(/([a-g]+|d+)/g);
    // ["ad", "be", "13"]
    •  / 字面量方式申明正则时的界定符
    'adobe'.match(/w+/);
    // ["adobe"]
    • 普通反斜线字符
    'a\dobe'.match(/\/);
    // [""]

    5. 小括号用法

    正则在非全局(g)模式下,通过match方式,返回的数组第一个值整体匹配的字符串,其他值为通过括号分组匹配到的

    (1) 捕获用法

    • 表示对匹配的字符串进行分组
    'adobe cs9cs10, adobe cs11'.match(/([a-z]+d+)+/);
    // ["cs9cs10", "cs10"]
    // 注意{2,}是对 括弧内的匹配 的描述
    • 与|一起使用表示选择性
    "he is 12. she is 13. it's box".match(/(it|she|he)s+is/g);
    // ["he is", "she is"]
    • 表示对匹配的字符串捕获
    'adobe cs9'.match(/[a-z]+d+/);
    // ["cs9"]
    'adobe cs9'.match(/[a-z]+(d+)/);
    // ["cs9", "9"]
    • 表示对匹配的字符串反向引用,引用从 1 开始,从正则左侧第一个左括号(当然要是闭合的括号才行)开始计算,每多一对括号,引用数加一,在非捕获情况下不会加一。但正则比较复杂时,减少引用可以提升匹配性能,关于 非捕获 下方会详细介绍
      引用的结果可以通过 构造函数 RegExp 获取,即 RegExp.9

    'Can you can a can as a canner can can a can?'.match(/([cC]an+)s+1/g);
    // ["can can"]
    // 注意 `1` 等价于正则里的 `([a-z]+)`,即与下面示例相同
    'Can you can a can as a canner can can a can?'.match(/[cC]an+s+[cC]an+/g);
    // ["can can"]
    
    // 如果把括弧去掉可以看下结果
    'Can you can a can as a canner can can a can?'.match(/[cC]an+s+1/g);
    // null

    (2) 非捕获用法,以(?)形式出现

    • (?:n ) 表示非捕获组
    // 不使用括号时
    'adobe12ps15test'.match(/[a-z]+d+[a-z]+/);
    // ["adobe12ps"]
    //使用括号分组
    'adobe12ps15test'.match(/[a-z]+(d+)([a-z]+)/);
    // ["adobe12ps", "12", "ps"]
    
    'adobe12ps15test'.match(/[a-z]+(?:d+)([a-z]+)/);
    // ["adobe12ps", "ps"]

    看起来上面语句不用(?:)也可以得到相同结果,即:

    'adobe12ps15test'.match(/[a-z]+d+([a-z]+)/);
    // ["adobe12ps", "ps"]

    但需求希望匹配字母之间的规则复杂时,如希望匹配字母,且字母之间可以为1或3时,但不需要1和3

    'adobe11ps15test'.match(/[a-z]+(1|3)+([a-z]+)/);
    // ["adobe11ps", "1", "ps"]

    返回中不希望包含数字怎么办,可以使用非捕获

    'adobe11ps15test'.match(/[a-z]+(?:1|3)+([a-z]+)/);
    // ["adobe11ps", "ps"]
    • (?=n ) 匹配任何其后紧跟字符n的字符串,但返回中不包含n
    'adobe12ps15test'.match(/[a-z]+(?=d)/g);
    // ["adobe", "ps"]
    • (?!n ) 匹配任何其后没有紧跟字符n的字符串,返回中不包含n
    'adobe12ps15test'.match(/[a-z]+(?!d)/g);
    // ["adob", "p", "test"]
    • (?<=n ) 匹配任何其前紧跟字符n的字符串,返回中不包含n
    'adobe12ps15test'.match(/(?<=d)[a-z]+/g);
    // ["ps", "test"]
    •  (?<!n ) 匹配任何其前紧跟字符n的字符串,返回中不包含n
    'adobe12ps15test'.match(/(?<!d)[a-z]+/g);
    // ["adobe", "s", "est"]

    (3) 注意

    • 如果希望对上面特殊字符本身进行匹配,需要在其前面添加进行转移
    '11+2=13'.match(/d++/g); 
    // ["11+"]
    '(11+2)*2=26'.match(/(d++d+)/g); 
    // ["(11+2)"]
    • 举例
    // 注意下面两个表达式返回的结果
    'path C:WindowsSystem32'.match(/([a-zA-Z]:\w+)/g); 
    // null
    'path C:\Windows\System32'.match(/([a-zA-Z]:\w+)/g); 
    // ["C:Windows"]
    说明:在申明字符串 'path C:WindowsSystem32' 时,其中的 '' 就已经被当做转移符,既是 'W' ==='W',所以如果希望申明的字符串中包含反斜线,需要在加一个反斜线转义,即
    6. 正则相关方法

    (1) RegExp对象相关方法

    (2) String对象相关方法

    (3) replace 具体用法

    顾名思义,是字符串替换方法,但用法比较广泛。

    • 基本用法

    直接传入字符串进行替换,找到子串后只替换一次,举例:

    'adobe abc'.replace('b', '_')
    // "ado_e abc"
    // 注意 第二个 b 没有被替换

    如果希望全部替换,可以使用正则表达式并用全局修饰符 g 方式,举例:

    'adobe abc'.replace(/b/g, '_')
    // "ado_e a_c"
    • 高级用法

    第二个参数可以使用 function,其中有三个参数,分别为 匹配的字符串、当前匹配的字符串index值、匹配的源字符串,最终结果根据每次匹配结果进行相应的替换。

    'adobe aacc bbaa'.replace(/a+/g, function(str, index, source){
        if(index > 0){
            return str.toUpperCase();
        } else {
            return str;
        }
    });
    // "adobe AAcc bbAA"

    三、案例分析

    1. 常见匹配

    在写正则之前,需要注意以下几点:

    • 一定要清楚期望的规则是什么,不然无从匹配
    • 有些正则不只一种写法,要注意简短干练,复杂的正则表达式不仅难懂,而且容易出BUG,性能也不是很好
    • 正则虽好,可要适度。有些字符串处理不一定适合用正则
  • 相关阅读:
    笔记-归并排序
    Repeated Substring Pattern
    Assign Cookies
    Number of Boomerangs
    Paint Fence
    Path Sum III
    Valid Word Square
    Sum of Two Integers
    Find All Numbers Disappeared in an Array
    First Unique Character in a String
  • 原文地址:https://www.cnblogs.com/myitnews/p/11780163.html
Copyright © 2011-2022 走看看