美文网首页JavaScript 进阶营
JavaScript--03 正则表达式详解及实例应用

JavaScript--03 正则表达式详解及实例应用

作者: 邪人君子 | 来源:发表于2020-04-23 09:37 被阅读0次

    欢迎移步

      RegExp:是正则表达式(regular expression)的简写。
      正则表达式常常用来按照“给定模式”匹配文本。比如,正则表达式给出一个 Email 地址的模式,然后用它来确定一个字符串是否为 Email 地址。
      参考地址一
      参考地址二
      参考地址三

    一、RegExp 对象属性和修饰符

    1.1 RegExp 对象属性

      RegExp 的每个实例都具有下列属性,通过这些属性可以取得有关模式的各种信息。

    • global:布尔值,表示是否设置了 g 标志。
    • ignoreCase:布尔值,表示是否设置了 i 标志。
    • multiline:布尔值,表示是否设置了 m 标志。
    • source:用于返回模式匹配所用的文本。
    • lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从 0 算起,可以手动指定位置开始匹配。

      下例中第一个模式使用的是字面量,第二个模式使用了 RegExp 构造函数,字面量方式效率较高且较为直观,所以更为常用。它们的source 属性是相同的。

    var pattern1 = /\[bc\]at/i; 
    alert(pattern1.global); //false 
    alert(pattern1.ignoreCase); //true 
    alert(pattern1.multiline); //false 
    alert(pattern1.lastIndex); //0 
    alert(pattern1.source); //"\[bc\]at" 
    
    var pattern2 = new RegExp("\\[bc\\]at", "i"); 
    alert(pattern2.global); //false 
    alert(pattern2.ignoreCase); //true 
    alert(pattern2.multiline); //false 
    alert(pattern2.lastIndex); //0 
    alert(pattern2.source); //"\[bc\]at" 
    

    1.2 修饰符

    1.2.1 g 修饰符

      默认情况下,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。

    var regex = /b/;
    var str = 'abba';
    
    regex.test(str); // true
    regex.test(str); // true
    regex.test(str); // true
    

      上面代码中,正则模式不含g修饰符,每次都是从字符串头部开始匹配。所以,连续做了三次匹配,都返回true。

    var regex = /b/g;
    var str = 'abba';
    
    regex.test(str); // true
    regex.test(str); // true
    regex.test(str); // false
    

      上面代码中,正则模式含有g修饰符,每次都是从上一次匹配成功处,开始向后匹配。因为字符串abba只有两个b,所以前两次匹配结果为true,第三次匹配结果为false。

    1.2.2 i 修饰符

      默认情况下,正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写(ignoreCase)。

    /abc/.test('ABC') // false
    /abc/i.test('ABC') // true
    

      上面代码表示,加了i修饰符以后,不考虑大小写,所以模式abc匹配字符串ABC。

    1.2.3 m 修饰符

      m修饰符表示多行模式(multiline),会修改^和$的行为。默认情况下(即不加m修饰符时),^和$匹配字符串的开始处和结尾处,加上m修饰符以后,^和$还会匹配行首和行尾,即^和$会识别换行符(\n)。

    /world$/.test('hello world\n') // false
    /world$/m.test('hello world\n') // true
    

      上面的代码中,字符串结尾处有一个换行符。如果不加m修饰符,匹配不成功,因为字符串的结尾不是world;加上以后,$可以匹配行尾。

    /^b/m.test('a\nb') // true
    

      上面代码要求匹配行首的b,如果不加m修饰符,就相当于b只能处在字符串的开始处。加上b修饰符以后,换行符\n也会被认为是一行的开始。

    二、RegExp 对象方法

    2.1 exec() 方法

      exec()接受一个字符串参数,如果字符串中有匹配的值返回该匹配值,否则返回 null:

    var s = '_x_x';
    var r1 = /x/;
    var r2 = /y/;
    
    r1.exec(s) // ["x"]
    r2.exec(s) // null
    

      如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。

    var s = '_x_x';
    var r = /_(x)/;
    
    r.exec(s) // ["_x", "x"]
    

      返回的数组虽然是 Array 的实例,但包含两个额外的属性:index 和 input。
      index 表示匹配项在字符串中的位置,从0开始计数。
      input 表示应用正则表达式的字符串。
      请看下面的例子。

    var text = "mom and dad and baby"; 
    var pattern = /mom( and dad( and baby)?)?/gi; 
    var matches = pattern.exec(text); 
    alert(matches.index); // 0 
    alert(matches.input); // 原字符串:"mom and dad and baby" 
    alert(matches[0]); // 第一个匹配项: "mom and dad and baby" 
    alert(matches[1]); // 第二个匹配项: " and dad and baby" 
    alert(matches[2]); // 第三个匹配项: " and baby" 
    

      对于 exec()方法而言,即使在模式中设置了全局标志(g),它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用 exec()将始终返回第一个匹配项的信息。而在设置全局标志的情况下,每次调用 exec()则都会在字符串中继续查找新匹配项,如下面的例子所示。

    var reg = /a/g;
    var str = 'abc_abc_abc'
    
    var r1 = reg.exec(str);
    r1 // ["a"]
    r1.index // 0
    reg.lastIndex // 1
    
    var r2 = reg.exec(str);
    r2 // ["a"]
    r2.index // 4
    reg.lastIndex // 5
    
    var r3 = reg.exec(str);
    r3 // ["a"]
    r3.index // 8
    reg.lastIndex // 9
    
    var r4 = reg.exec(str);
    r4 // null
    reg.lastIndex // 0
    

      上面代码连续用了四次exec() 方法,前三次都是从上一次匹配结束的位置向后匹配。当第三次匹配结束以后,整个字符串已经到达尾部,匹配结果返回null,正则实例对象的lastIndex属性也重置为0,意味着第四次匹配将从头开始。

      利用g修饰符允许多次匹配的特点,可以用一个循环完成全部匹配。

    var reg = /a/g;
    var str = 'abc_abc_abc'
    
    while(true) {
      var match = reg.exec(str);
      if (!match) break;
      console.log('#' + match.index + ':' + match[0]);
    }
    // #0:a
    // #4:a
    // #8:a
    

      上面代码中,只要exec方法不返回null,就会一直循环下去,每次输出匹配的位置和匹配的文本。

    2.2 test() 方法

      正则表达式的第二个方法是 test(),它接受一个字符串参数。在模式与该参数匹配的情况下返回 true;否则,返回 false。
      test()方法经常被用在 if 语句中,如下面的例子所示。

    var text = "000-00-0000"; 
    var pattern = /\d{3}-\d{2}-\d{4}/; 
    if (pattern.test(text)){ 
     alert("The pattern was matched."); 
    } 
    

      在这个例子中,如果输入的文本与模式匹配,则显示一条消息。这种用法经常出现在验证用户输入的情况下,因为我们只想知道输入是不是有效,至于它为什么无效就无关紧要了。
      如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。

    var r = /x/g;
    var s = '_x_x';
    
    r.lastIndex // 0
    r.test(s) // true
    
    r.lastIndex // 2
    r.test(s) // true
    
    r.lastIndex // 4
    r.test(s) // false
    

      带有g修饰符时,可以通过正则对象的lastIndex属性指定开始搜索的位置。下例代码中,指定从字符串的第五个位置开始搜索,这个位置为空,所以返回false。同时,lastIndex属性重置为0,所以第二次执行r.test(s)会返回true。

    var r = /x/g;
    var s = '_x_x';
    
    r.lastIndex = 4;
    r.test(s) // false
    
    r.lastIndex // 0
    r.test(s)
    

    2.3 toLocaleString() 和 toString() 方法

      RegExp 实例继承的 toLocaleString()和 toString()方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。例如:

    var pattern = new RegExp("\\[bc\\]at", "gi"); 
    alert(pattern.toString()); // /\[bc\]at/gi 
    alert(pattern.toLocaleString()); // /\[bc\]at/gi
    alert(pattern.source); // \[bc\]at 
    

    三、字符串的实例方法

      字符串的实例方法之中,有4种与正则表达式有关。

    • String.match():返回一个数组,成员是所有匹配的子字符串。
    • String.search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。
    • String.replace():按照给定的正则表达式进行替换,返回替换后的字符串。
    • String.split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。

    3.1 match() 方法

      字符串的 match() 方法与正则对象的 exec() 方法非常类似:匹配成功返回一个数组,匹配失败返回null。

    var s = '_x_x';
    var r1 = /x/;
    var r2 = /y/;
    
    s.match(r1) // ["x"]
    s.match(r2) // null
    

      如果正则表达式带有 g 修饰符,则该方法与正则对象的 exec() 方法行为不同,会一次性返回所有匹配成功的结果。
      设置正则表达式的 lastIndex 属性,对 match() 方法无效,匹配总是从字符串的第一个字符开始。

    var s = 'abba';
    var r = /a/g;
    
    s.match(r) // ["a", "a"]
    r.exec(s) // ["a"]
    

    3.2 search() 方法

      字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有任何匹配,则返回-1。

    '_x_x'.search(/x/)
    // 1
    

    3.3 replace() 方法

      字符串对象的 replace() 方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。

    str.replace(search, replacement)
    

      正则表达式如果不加 g 修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值。

    'aaa'.replace('a', 'b') // "baa"
    'aaa'.replace(/a/, 'b') // "baa"
    'aaa'.replace(/a/g, 'b') // "bbb"
    

      replace方法的第二个参数还可以是一个函数,将每一个匹配内容替换为函数返回值。
    例一:

    '3 and 5'.replace(/[0-9]+/g, function (match) {
      return 2 * match;
    })
    // "6 and 10"
    

    例二:

    var a = 'The quick brown fox jumped over the lazy dog.';
    var pattern = /quick|brown|lazy/ig;
    
    a.replace(pattern, function replacer(match) {
      return match.toUpperCase();
    });
    // The QUICK BROWN fox jumped over the LAZY dog.
    

    3.4 split() 方法

      字符串对象的split方法按照正则规则分割字符串,返回一个由分割后的各个部分组成的数组。
      该方法接受两个参数,第一个参数是正则表达式,表示分隔规则,第二个参数是返回数组的最大成员数。

    // 非正则分隔
    'a,  b,c, d'.split(',')
    // [ 'a', '  b', 'c', ' d' ]
    
    // 正则分隔,去除多余的空格
    'a,  b,c, d'.split(/, */)
    // [ 'a', 'b', 'c', 'd' ]
    
    // 指定返回数组的最大成员
    'a,  b,c, d'.split(/, */, 2)
    [ 'a', 'b' ]
    

      split() 方法用于把一个字符串分割成字符串数组。
      提示: 如果把空字符串 ("") 用作 separator,那么 stringObject 中的每个字符之间都会被分割。
      注意: split() 方法不改变原始字符串。

    四、匹配规则

    4.1 字面量字符和元字符

      大部分字符在正则表达式中,就是字面的含义,比如/a/匹配a,/b/匹配b。如果在正则表达式之中,某个字符只表示它字面的含义(就像前面的a和b),那么它们就叫做“字面量字符”(literal characters)。
      除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。它们叫做“元字符”(metacharacters),主要有以下几个。

    4.1.1 点字符(.)

      点字符(.)匹配除换行和行结束符以外的单个字符,包括空格。

    /c.t/
    

      上面代码中,c.t匹配c和t之间包含任意一个字符的情况,只要这三个字符在同一行,比如cat、c2t、c-t等等,但是不匹配coot。

    4.1.2 位置字符(^,$)

      位置字符用来提示字符所处的位置,主要有两个字符。

    • ^n 匹配任何开头为 n 的字符串。
    • n$ 匹配任何结尾为 n 的字符串。
    // test必须出现在开始位置
    /^test/.test('test123') // true
    
    // test必须出现在结束位置
    /test$/.test('new test') // true
    
    // 从开始位置到结束位置只有test
    /^test$/.test('test') // true
    /^test$/.test('test test') // false
    

    4.1.3 选择符(|)

      竖线符号(|)在正则表达式中表示“或关系”(OR),即cat|dog表示匹配cat或dog。

    /11|22/.test('911') // true
    

      上面代码中,正则表达式指定必须匹配11或22。

    4.1.4 转义符(\)

      正则表达式中那些有特殊含义的元字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠。比如要匹配+,就要写成+。

    /1+1/.test('1+1')
    // false
    
    /1\+1/.test('1+1')
    // true
    

      上面代码中,第一个正则表达式之所以不匹配,因为加号是元字符,不代表自身。第二个正则表达式使用反斜杠对加号转义,就能匹配成功。

      正则表达式中,需要反斜杠转义的,一共有12个字符:^、.、[、$、(、)、|、*、+、?、{和\。需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。

    (new RegExp('1\+1')).test('1+1')
    // false
    
    (new RegExp('1\\+1')).test('1+1')
    // true
    

      上面代码中,RegExp作为构造函数,参数是一个字符串。但是,在字符串内部,反斜杠也是转义字符,所以它会先被反斜杠转义一次,然后再被正则表达式转义一次,因此需要两个反斜杠转义。

    4.2 量词符

    4.2.1 重复类({n,m})

      模式的精确匹配次数,使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。

    /lo{2}k/.test('look') // true
    /lo{2,5}k/.test('looook') // true
    

      上面代码中,第一个模式指定o连续出现2次,第二个模式指定o连续出现2次到5次之间。

    4.2.2 问号符(?)

    ? 问号表示某个模式出现0次或1次,等同于{0, 1}。

    // t 出现0次或1次
    /t?est/.test('test') // true
    /t?est/.test('est') // true
    

    4.2.3 星号符(*)

    *星号表示某个模式出现0次或多次,等同于{0,}。

    // t 出现0次或多次
    /t*est/.test('test') // true
    /t*est/.test('ttest') // true
    /t*est/.test('tttest') // true
    /t*est/.test('est') // true
    

    4.2.4 加号符(+)

    + 加号表示某个模式出现1次或多次,等同于{1,}。

    // t 出现1次或多次
    /t+est/.test('test') // true
    /t+est/.test('ttest') // true
    /t+est/.test('est') // false
    

    4.3 贪婪模式

    4.3.1 贪婪模式

    上一小节的三个量词符,默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止。这被称为贪婪模式。

    var s = 'aaa';
    s.match(/a+/) // ["aaa"]
    

    上面代码中,模式是/a+/,表示匹配1个a或多个a,那么到底会匹配几个a呢?因为默认是贪婪模式,会一直匹配到字符a不出现为止,所以匹配结果是3个a。

    4.3.2 非贪婪模式

    如果想将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。

    • +?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。
    • *?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。
    • ??:表格某个模式出现0次或1次,匹配时采用非贪婪模式。
    var s = 'aaa';
    s.match(/a+?/) // ["a"]
    

    上面代码中,模式结尾添加了一个问号/a+?/,这时就改为非贪婪模式,一旦条件满足,就不再往下匹配。

    除了非贪婪模式的加号,还有非贪婪模式的星号(*)和非贪婪模式的问号(?)。

    'abb'.match(/ab*b/) // ["abb"]
    'abb'.match(/ab*?b/) // ["ab"]
    
    'abb'.match(/ab?b/) // ["abb"]
    'abb'.match(/ab??b/) // ["ab"]
    

    4.4 字符类

    表达式 描述
    [abc] 查找方括号之间的任何字符。
    [^abc] 查找任何不在方括号之间的字符。
    [0-9] 查找任何从 0 至 9 的数字。
    [a-z] 查找任何从小写 a 到小写 z 的字符。
    [A-Z] 查找任何从大写 A 到大写 Z 的字符。
    [A-z] 查找任何从大写 A 到小写 z 的字符。
    [adgk] 查找给定集合内的任何字符。
    [^adgk] 查找给定集合外的任何字符。

    4.4.1 方括号 [abc]

      所有可供选择的字符都放在方括号内,比如[xyz] 表示x、y、z之中任选一个匹配。

    /[abc]/.test('hello world') // false
    /[abc]/.test('apple') // true
    

      上面代码中,字符串hello world不包含a、b、c这三个字母中的任一个,所以返回false;字符串apple包含字母a,所以返回true。

    4.4.2 脱字符([^abc])

      如果方括号内的第一个字符是 [^],则表示除了字符类之中的字符,其他字符都可以匹配。比如,[^xyz]表示除了x、y、z之外都可以匹配。
      注意,脱字符只有在字符类的第一个位置才有特殊含义,否则就是字面含义。

    /[^abc]/.test('hello world') // true
    /[^abc]/.test('bbc') // false
    

      上面代码中,字符串hello world不包含字母a、b、c中的任一个,所以返回true;字符串bbc包含a、b、c中的字母,所以返回false。

      如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符。相比之下,点号作为元字符(.)是不包括换行符的。

    var s = 'Please yes\nmake my day!';
    
    s.match(/yes.*day/) // null
    s.match(/yes[^]*day/) // [ 'yes\nmake my day']
    

      上面代码中,字符串s含有一个换行符,点号不包括换行符,所以第一个正则表达式匹配失败;第二个正则表达式[^]包含一切字符,所以匹配成功。

    4.4.3 连字符([a-c])

      [abc]可以写成[a-c],[0123456789]可以写成[0-9],同理[A-Z]表示26个大写字母。

    /a-z/.test('b') // false
    /[a-z]/.test('b') // true
    

    上面代码中,当连字号(dash)不出现在方括号之中,就不具备简写的作用,只代表字面的含义,所以不匹配字符b。只有当连字号用在方括号之中,才表示连续的字符序列。

    以下都是合法的字符类简写形式。

    [0-9.,]
    [0-9a-fA-F]
    [a-zA-Z0-9-]
    [1-31]   //  只代表 1~3
    

    4.5 其他字符

    元字符 描述
    \w 匹配任意的字母、数字和下划线,不含空格,相当于[A-Za-z0-9_]。
    \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。
    \d 查找数字,相当于[0-9]。
    \D 查找非数字字符,相当于[^0-9]。
    \s 匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]。
    \S 匹配非空格的字符,相当于[^ \t\r\n\v\f]。
    \b 匹配单词边界。
    \B 匹配非单词边界。
    \0 查找 NULL 字符。
    \n 查找换行符。
    \f 查找换页符。
    \r 查找回车符。
    \t 查找制表符。
    \v 查找垂直制表符。
    \xxx 查找以八进制数 xxx 规定的字符。
    \xdd 查找以十六进制数 dd 规定的字符。
    \uxxxx 查找以十六进制数 xxxx 规定的 Unicode 字符。
    // \s 的例子
    /\s\w*/.exec('hello world') // [" world"]
    
    // \b 的例子
    // \b表示词的边界,所以world的词首必须独立(词尾是否独立未指定),才会匹配。
    /\bworld/.test('hello world') // true
    /\bworld/.test('hello-world') // true
    /\bworld/.test('helloworld') // false
    
    // \B 的例子
    /\Bworld/.test('hello-world') // false
    /\Bworld/.test('helloworld') // true
    
    var html = "<b>Hello</b>\n<i>world!</i>";
    
    // . 不匹配换行符
    /.*/.exec(html)[0]
    // "<b>Hello</b>"
    
    /[\S\s]*/.exec(html)[0]
    // "<b>Hello</b>\n<i>world!</i>"
    // [\S\s]指代一切字符。
    

    五、组匹配

    5.1 捕获组 (x)

    正则表达式的括号 () 表示分组匹配,括号中的模式可以用来匹配分组的内容。
    例一:

    /fred+/.test('fredd') // true
    /(fred)+/.test('fredfred') // true
    

    上面代码中,第一个模式没有括号,结果+只表示重复字母d,第二个模式有括号,结果+就表示匹配fred这个词。

    例二:

    var m = 'abcabc'.match(/(.)b(.)/);
    m
    // ['abc', 'a', 'c']
    

    上面代码中,正则表达式/(.)b(.)/一共使用两个括号,第一个括号捕获a,第二个括号捕获c。

    注意,使用组匹配时,不宜同时使用g修饰符,否则match方法不会捕获分组的内容。

    var m = 'abcabc'.match(/(.)b(.)/g);
    m // ['abc', 'abc']
    

    上面代码使用带g修饰符的正则表达式,结果match方法只捕获了匹配整个表达式的部分。这时必须使用正则表达式的exec方法,配合循环,才能读到每一轮匹配的组捕获:

    var str = 'abcabc';
    var reg = /(.)b(.)/g;
    while (true) {
      var result = reg.exec(str);
      if (!result) break;
      console.log(result);
    }
    // ["abc", "a", "c"]
    // ["abc", "a", "c"]
    

    正则表达式内部,还可以用\n引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号。

    /(.)b(.)\1b\2/.test("abcabc")
    // true
    

    上面的代码中,\1表示第一个括号匹配的内容(即a),\2表示第二个括号匹配的内容(即c)。

    下面是另外一个例子。

    /y(..)(.)\2\1/.test('yabccab') // true
    

    括号还可以嵌套。

    /y((..)\2)\1/.test('yabababab') // true
    

    上面代码中,\1指向外层括号,\2指向内层括号。

    组匹配非常有用,下面是一个匹配网页标签的例子。

    var tagName = /<([^>]+)>[^<]*<\/\1>/;
    
    tagName.exec("<b>bold</b>")[1]
    // 'b'
    

    上面代码中,圆括号匹配尖括号之中的标签,而\1就表示对应的闭合标签。

    5.2 非捕获组 (?:x)

    (?:x)称为非捕获组(Non-capturing group),表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。

    请看下面的例子。

    var m = 'abc'.match(/(?:.)b(.)/);
    m // ["abc", "c"]
    

    上面代码中的模式,一共使用了两个括号。其中第一个括号是非捕获组,所以最后返回的结果中没有第一个括号,只有第二个括号匹配的内容。

    下面是用来分解网址的正则表达式。

    // 正常匹配
    var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
    
    url.exec('http://google.com/');
    // ["http://google.com/", "http", "google.com", "/"]
    
    // 非捕获组匹配
    var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
    
    url.exec('http://google.com/');
    // ["http://google.com/", "google.com", "/"]
    

    上面的代码中,前一个正则表达式是正常匹配,第一个括号返回网络协议;后一个正则表达式是非捕获匹配,返回结果中不包括网络协议。

    5.3 先行断言 x(?=y)

    x(?=y)称为先行断言(Positive look-ahead),x只有在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟着百分号的数字,可以写成/\d+(?=%)/

    “先行断言”中,括号里的部分是不会返回的。

    var m = 'abc'.match(/b(?=c)/);
    m // ["b"]
    

    上面的代码使用了先行断言,b在c前面所以被匹配,但是括号对应的c不会被返回。

    5.4先行否定断言 x(?!y)

    x(?!y)称为先行否定断言(Negative look-ahead),x只有不在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟的不是百分号的数字,就要写成/\d+(?!%)/

    /\d+(?!\.)/.exec('3.14')
    // ["14"]
    

    上面代码中,正则表达式指定,只有不在小数点前面的数字才会被匹配,因此返回的结果就是14。

    “先行否定断言”中,括号里的部分是不会返回的。

    var m = 'abd'.match(/b(?!c)/);
    m // ['b']
    

    上面的代码使用了先行否定断言,b不在c前面所以被匹配,而且括号对应的d不会被返回。

    六、正则表达式应用——实例应用

    1.验证用户名和密码:("^[a-zA-Z]\w{5,15}$")正确格式:"[A-Z][a-z]_[0-9]"组成,并且第一个字必须为字母6~16位;
    2.验证电话号码:("^(\d{3,4}-)\d{7,8}$")正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;
    3.验证手机号码:"^1[3|4|5|7|8][0-9]{9}$";
    4.验证身份证号(15位):"\d{14}[[0-9],0-9xX]",(18位):"\d{17}(\d|X|x)";
    5.验证Email地址:("^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
    6.只能输入由数字和26个英文字母组成的字符串:("^[A-Za-z0-9]+$");
    7.整数或者小数:^[0-9]+([.][0-9]+){0,1}$
    8.只能输入数字:"^[0-9]*$"。
    9.只能输入n位的数字:"^\d{n}$"。
    10.只能输入至少n位的数字:"^\d{n,}$"。
    11.只能输入m~n位的数字:"^\d{m,n}$"。
    12.只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
    13.只能输入有两位小数的正实数:"^[0-9]+(\.[0-9]{2})?$"。
    14.只能输入有1~3位小数的正实数:"^[0-9]+(\.[0-9]{1,3})?$"。
    15.只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
    16.只能输入非零的负整数:"^\-[1-9][0-9]*$"。
    17.只能输入长度为3的字符:"^.{3}$"。
    18.只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
    19.只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
    20.只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
    21.验证是否含有^%&',;=?$\"等字符:"[%&',;=?$\\^]+"。
    22.只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"。
    23.验证URL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
    24.验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"10"~"12"。
    25.验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"、"10"~"29"和“30”~“31”。
    26.获取日期正则表达式:\\d{4}[年|\-|\.]\d{\1-\12}[月|\-|\.]\d{\1-\31}日?
    评注:可用来匹配大多数年月日信息。
    27.匹配双字节字符(包括汉字在内):[^\x00-\xff]
    评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
    28.匹配空白行的正则表达式:\n\s*\r
    评注:可以用来删除空白行
    29.匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?</>|<.*? />
    评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
    30.匹配首尾空白字符的正则表达式:^\s*|\s*$
    评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
    31.匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
    评注:网上流传的版本功能很有限,上面这个基本可以满足需求
    32.匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
    评注:表单验证时很实用
    33.匹配腾讯QQ号:[1-9][0-9]{4,}
    评注:腾讯QQ号从10 000 开始
    34.匹配中国邮政编码:[1-9]\\d{5}(?!\d)
    评注:中国邮政编码为6位数字
    35.匹配ip地址:([1-9]{1,3}\.){3}[1-9]。
    评注:提取ip地址时有用
    

    相关文章

      网友评论

        本文标题:JavaScript--03 正则表达式详解及实例应用

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