美文网首页
正则表达式

正则表达式

作者: 倩倩_a570 | 来源:发表于2020-04-27 20:51 被阅读0次

    什么是正则

    在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

    正则表达式到底能用来做什么

    1、测试字符串内的模式。
    可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式
    2、替换文本。
    可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
    3、基于模式匹配从字符串中提取子字符串。

    1 RegExp对象
    • 创建的两种方式:
      对象字面量 var reg = /is/;
      构造函数 var reg = new RegExp('\is');
    • 修饰符
      g :global 全文搜索
      I: ignore case 忽略大小写
      m:multiple lines多行搜索
    2 元字符

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

    字符 含义
    \t 水平制表符
    \v 垂直制表符
    \n 换行符
    \r 回车符
    3 字符类

    3-1. 字符组
    一般情况下 正则中的一个字符对应一个字符串。

    'abcdef'.match(/abc/g);  //["abc"]
    

    但是我们有的时候希望匹配某类字符就需要用到字符组(字符类),例如匹配一个字符,它可以是“a”、“b”、“c”其中之一。

    'abcdef'.match(/[abc]/g);  //["a", "b", "c"]
    

    3-2. 字符范围
    连字符-来省略和简写。[0-9] [a-z] [A-Z]
    比如[123456abcdefGHIJKLM],可以写成[1-6a-fG-M]
    注意 如果要匹配字符串中的"-" ,将"-"写在范围后面即可

    '2020-04-04'.replace(/[0-9-]/g,'A');//"AAAAAAAAAA"
    

    3-3 排除字符组
    某位字符可以是任何东西,但就不能是"a"、"b"、"c"。[^abc],表示是一个除"a"、"b"、"c"之外的任意一个字符。字符组的第一位放^(脱字符),表示求反的概念。

    'ABCDEF0123'.replace(/[^A-D]/g,'0'); //"ABCD000000"
    

    3-4预定义类

    字符 含义
    \d [0-9]表示是一位数字。d是digit的简写
    \D 就是[^0-9]。表示除数字外的任意字符。
    \w 就是[0-9a-zA-Z_]。表示数字、大小写字母和下划线。w是word的简写
    \W 是[^0-9a-zA-Z_]。非单词字符
    \s 是[ \t\v\n\r\f]。表示空白符。s是space character的简写。
    \S 是[^ \t\v\n\r\f]。 非空白符
    . 通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。

    如果要匹配任意字符怎么办?可以使用[\d\D]、[\w\W]、[\s\S]和[^]中任何的一个。

    //将数字替换成A
    'ABCDEF0123'.replace(/[\d]/g,'A');//"ABCDEFAAAA"
    //将非数字替换成X
    'ABCDEF0123'.replace(/[\D]/g,'X');//"XXXXXX0123"
    
    4 量词
    字符 含义
    ? 0次或一次
    + 至少出现一次
    * 任意次
    {n} 出现n次
    {n, m} 出现n到m次。
    {n, } 至少出现n次
    //匹配8位数字的QQ号码
    /^\d{8}$/g.test('12345678'); //true
    //匹配1开头11位数字的手机号码
    /^1\d{10}$/g.test('12345678910'); //true
    //匹配银行卡号是14~18位的数字:
    /^\d{14,18}$/g.test('12345678901234567'); //true
    //匹配以a开头的,0个或多个b结尾的字符串
    /^0b*$/g.test('0bbbb'); //true
    

    贪婪匹配和惰性匹配
    正则是贪婪模式,会尽可能多的匹配。

    var regex = /\d{2,5}/g;
    var string = "123456";
    console.log( string.match(regex) ); //["12345"]
    

    而惰性匹配,就是尽可能少的匹配,通过在量词后面加个问号就能实现惰性匹配,因此所有惰性匹配情形如下:

    var regex = /\d{2,5}?/g;
    var string = "123456";
    console.log( string.match(regex) ); //["12", "34", "56"]
    
    5边界
    字符 含义
    ^ 匹配开头,在多行匹配中匹配行开头
    $ 匹配结尾,在多行匹配中匹配行结尾
    \b boundary ,单词边界
    \B \B就是\b的反面的意思,非单词边界
    (?=p) 正向先行断言,也叫正向前瞻。其中p是一个子模式,即p前面的位置
    (?!p) 负向先行断言,也叫负向前瞻。即p后面的位置

    ^和&

    //比如我们把字符串的开头和结尾用"#"替换
    var result = "hello".replace(/^|$/g, '#');
    console.log(result); //  "#hello#"
    

    \b和\B

    var result = "[JS] Lesson_01.mp4".replace(/\b/g, '#');
    console.log(result); //"[#JS#] #Lesson_01#.#mp4#"
    

    \b是单词边界,具体就是\w和\W之间的位置,也包括\w和^之间的位置,也包括\w和$之间的位置。
    首先,我们知道,\w是字符组[0-9a-zA-Z_]的简写形式,即\w是字母数字或者下划线的中任何一个字符。
    而\W是排除字符组[^0-9a-zA-Z_]的简写形式,即\W是\w以外的任何一个字符。
    此时我们可以看看"[#JS#] #Lesson_01#.#mp4#"中的每一个"#",是怎么来的。

    1.第一个"#",两边是"["与"J",是\W和\w之间的位置。
    2.第二个"#",两边是"S"与"]",也就是\w和\W之间的位置。
    3.第三个"#",两边是空格与"L",也就是\W和\w之间的位置。
    4.第四个"#",两边是"1"与".",也就是\w和\W之间的位置。
    5.第五个"#",两边是"."与"m",也就是\W和\w之间的位置。
    6.第六个"#",其对应的位置是结尾,但其前面的字符"4"是\w,即\w和$之间的位置。
    \B就是\b的反面的意思,非单词边界。例如在字符串中所有位置中,扣掉\b,剩下的都是\B的。

    再举个例子,要将"This is an apple."中的is替换成"X"。

    'This is an apple'.replace(/is/,'X');//"ThX is an apple"
    

    这样会将单词中的is 一起匹配替换掉,如果指向匹配 单词"is"

    'This is an apple'.replace(/\bis\b/,'X');//"This X an apple"
    

    如果只想讲"This"中的"is"替换掉

    'This is an apple'.replace(/\Bis/,'X');//"ThX is an apple"
    

    (?=p)和(?!p)
    (?=X),表示前面是'X'字符的位置,(?!X)表示前面不是'X'字符位置例如:

    'ABCD'.replace(/(?=D)/,"X");//"ABCXD"
    'ABCD'.replace(/(?!B)/g,"X");//"XABXCXDX"
    

    *注意正则表达式从文本头部向尾部开始解析,文本尾部方向称为前。前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言。(和正常理解的前后不同,要注意一下)

    6正则中的括号

    分组
    量词是作用于紧挨着的字符,例如/^ab+$/ 会匹配到'abbb' 而不是'abab'
    如果我们想匹配到'abab' 就要用/^(ab)+$/

    /^ab+$/.test('abab'); //false
    /^ab+$/.test('abbb'); //false
    
    /^(ab)+$/.test('abab'); //true
    /^(ab)+$/.test('abbb'); //false
    

    分支结构
    或'|': 多个分支可以走任意一个 (aaa | bbb)

    'JasperDasper'.replace(/(J|D)asper/g,'X'); //"XX"
    

    如果不加括号则是匹配到'|' 前后的所有字符

    var regex = /^I love (JavaScript|Regular Expression)$/;
    console.log( regex.test("I love JavaScript") );//true
    console.log( regex.test("I love Regular Expression") );//true
    

    引用

    var regex = /(\d{4})-(\d{2})-(\d{2})/;
    var string = "2017-06-12";
    string.replace(regex,'$1/$2/$3'); //"2017/06/12"
    string.replace(regex,'$2/$3/$1'); //"06/12/2017"
    

    上例中,我们用()将表达式分为了三组,在replace方法中$1、$2、$3指代相应的分组。

    反向引用
    正则本身里引用分组。但只能引用之前出现的分组,即反向引用。
    例如需要验证"2017-06-12","2017/06/12" "2017.06.12" "2016-06/12",这几种格式的日期,我们可以用/\d{4}(-|/|.)\d{2}\1\d{2}/,其中(-|/|.)是一个分组,而\1就是引用的该分组的内容

    var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
    var string1 = "2017-06-12";
    var string2 = "2017/06/12";
    var string3 = "2017.06.12";
    var string4 = "2016-06/12";
    console.log( regex.test(string1) ); // true
    console.log( regex.test(string2) ); // true
    console.log( regex.test(string3) ); // true
    console.log( regex.test(string4) ); // false
    

    非捕获分组
    也称为忽略分组,不希望捕获某些分组时,只需要在分组内加上?:即可
    例如 (?:Byron).(ok) 在引用\1时 ,会引用到(ok),分组 (?:Byron).已被忽略。

    常用方法

    属性
    global:是否全文搜索,默认false
    ignore case:是否大小写敏感,默认false
    multiline:多行搜索,默认值是false
    lastIndex:是当前表达式匹配内容的最后一个字符的下一个位置
    source:正则表达式的文本字符串

    var reg1 = /\w/;
    var reg2 = /\w/gim;
    reg1.global;//false
    reg2.global://true
    reg1.ignoreCase://false
    reg2.ignoreCase:;//true
    reg1.multiline;//false
    reg2.multiline;//true
    reg1.lastIndex;//0
    reg2.lastIndex;//0
    reg1.source;//"\w"
    reg2.source;//"\w"
    

    在RegExp对象中:
    1:test
    定义:检测一个字符串是否匹配某个模式。

    /(abc)+/.test("abc123") // true
    

    2:exec
    定义:检索字符串中的正则表达式的匹配。

    如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。

    /([a-z])+(\d)+/.exec("abc123abc123abc123") // ["abc123", "c", "3", index: 0, input: "abc123abc123abc123", groups: undefined]
    

    非全局匹配:
    第 0 个元素是与正则表达式相匹配的文本,
    第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本
    第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本
    index 属性声明的是匹配文本的第一个字符的位置。
    input 属性则存放的是被检索的字符串 string。

    var str = 'asd1adf2ad3sdc4'
    var reg2 = /\d/g;
    reg2.exec(str);//["1", index: 3, input: "asd1adf2ad3sdc4", groups: undefined]
    reg2.exec(str);//["2", index: 7, input: "asd1adf2ad3sdc4", groups: undefined]
    reg2.lastIndex;//8
    reg2.lastIndex = 1;
    reg2.exec(str);//["1", index: 3, input: "asd1adf2ad3sdc4", groups: undefined]
    

    全局匹配:
    全局匹配模式下,此方法返回值依然是一个数组。和非全局匹配模式下完全一样。
    lastIndex属性用来规定正则表达式在字符串中开始检索的位置。
    exec方法可以与lastIndex属性配合使用。
    如果正则表达式匹配失败,那么lastIndex属性被重置为0。

    在String对象中:
    1:search
    定义:检索字符串中与指定的子字符串或正则表达式相匹配的子字符串。
    其他说明:该方法将忽略"g"标志和正则对象的lastIndex属性(即总是从开头找起),返回找到的第一个字符的位置,如果未找到返回-1。
    2:match
    定义:在字符串内查找一个或多个与正则表达式匹配的字符串,返回一个对象。
    非全局调用,返回一个对象,和exec非全局搜索时一样。
    全局调用时,返回的数组的内容与前者大不相同,它的数组元素中存放的是 stringObject 中所有的匹配子串,而且也没有 index 属性或 input 属性。

    var str="1 plus 2 equal 3"
    console.log(str.match(/\d+/g));//["1", "2", "3"]
    

    3:replace(yourRegexpOrString,placementString);
    定义:用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
    stringObject.replace(regexp/substr,replacement)
    replacement 可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。但是 replacement 中的 字符具有特定的含义。1、$2、 与 regexp 匹配的子表达式的文本。

    var string = 'className';
    string.replace(/[A-Z]/g,'x');//"classxame"
    var string 1 = 'world, hello';
    string1.replace(/(\w+)(?:\W*)(\w+)/,'$2 $1');//"hello world"
    var name = 'aaa bbb ccc';
    name.replace(/\b\w+\b/g, function(word){
      return word.substring(0,1).toUpperCase()+word.substring(1);
    });//"Aaa Bbb Ccc"
    

    4:split
    定义:把一个字符串分割成字符串值的数组。
    是arr.join(separatorString)反操作,如果传入"",则每个字符都将会被分隔到数组。howMany指定返回数组的个数。

    var a= 'banana';
    a.split(/a/);//["b", "n", "n", ""]
    

    如果正则表达式包含子表达式,那么返回的数组中包括与这些子表达式匹配的字串。

    var a= 'banana';
    a.split(/b(a)/);//["", "a", "nana"]
    a.split(/a/);//["b", "n", "n", ""]
    a.split(/a(n)/);//["b", "n", "", "n", "a"]
    

    参考链接:https://juejin.im/post/5965943ff265da6c30653879

    相关文章

      网友评论

          本文标题:正则表达式

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