跳至主要內容

13. 正则表达式

Harry Xiong大约 11 分钟Web 前端JavaScriptPromise 对象JS 异步async 与 await

正则表达式

正则表达式用于定义一些字符串的规则,计算机可以根据正则表达式,来检查一个字符串是否符合规则,获取字符串中符合规则的内容

基本概念

  • 正则表达式是由一个字符序列形成的搜索模式

  • 当在文本中搜索数据时,可以用搜索模式来描述要查询的内容

  • 正则表达式可以是一个简单的字符,或一个更复杂的模式

  • 正则表达式可用于所有文本搜索和文本替换的操作

13.1 创建正则表达式对象

正则表达式实质上也是一个对象

  • 构造函数创建正则表达式对象

    语法:var 变量=new RegExp("正则表达式","匹配模式")

    var reg=new RegExp("a");//可以不传入匹配模式
    

    正则表达式对象可以使用test()方法可以用来检查一个字符串是否符合正则表达式的规则,如果符合返回true,否则返回false

    var reg=new RegExp("a");
    var str="a";
    var str1="A"var result=reg.test(str);
    var result=reg.test(str1);
    console.log(result);//true
    console.log(result);//false
    //这种正则表达式可以检查一个字符串中是否含有a,严格区分大小写,如果不区分大小写可以传入第二个参数
    

    匹配模式

    正则表达式中有三种匹配模式

    • i 忽略大小写匹配
    • g 全局匹配(查找所有匹配而非在找到第一个匹配后停止)
    • m 多行匹配,作用是修改

      和$在正则表达式中的作用,让它们分别表示行首和行尾,在默认情况下,一个字符串无论是否换行只有一个开始

      和结尾,,

      注:三种匹配模式可以同时使用,写法与顺序无关

      var reg=new RegExp("a","i")//不区分大小写a
      var str="a";
      var str1="A"var result=reg.test(str);
      var result=reg.test(str1);
      console.log(result);//true
      console.log(result);//true
      
  • 使用字面量创建正则表达式

    语法:var 变量=/正则表达式/匹配模式

    var reg=/a/i;
    //多个匹配模式
    var reg2=/a/ig;
    

构造函数与创建字面量函数的区别

  • 使用字面量的方式创建更加简单

  • 使用构造函数创建更加灵活

13.2 正则符号

以下参考自w3cschool

  • 方括号,

    用于查找某个范围内的字符

    表达式描述
    [abc]查找方括号之间的任何字符。
    [^abc]查找任何不在方括号之间的字符。,只要一个字符串中有除了abc以外的字母就会返回true
    [0-9]查找任何从 0 至 9 的数字。
    [a-z]查找任何从小写 a 到小写 z 的字符。
    [A-Z]查找任何从大写 A 到大写 Z 的字符。
    [A-z]查找任何从大写 A 到小写 z 的字符。
    [adgk]查找给定集合内的任何字符。
    [^adgk]查找给定集合外的任何字符。
    (red|blue|green)查找任何指定的选项。
    var reg1=/ab/i; //检验一个字符串中是否有ab(整体)
    var reg2=/a|b/; //检查一个字符串中是否有a或b
    var reg3=/a|b|c/; //检查一个字符串中是否有a或b或c
    var reg4=/[ab]/;  //[]里面也是或的关系[ab]===a|b
    var reg5=/a[bde]c/; //查一个字符串中是否还有abc或adc或aec(整体)
    
  • 元字符,是拥有特殊含义的字符

    元字符描述
    .查找单个字符,除了换行和行结束符。
    \w查找单词字符。
    \W查找非单词字符。
    \d查找数字。
    \D查找非数字字符。
    \s查找空白字符。
    \S查找非空白字符。
    \b匹配单词边界。一个单词旁边必须是有空白字符作为边界。比如判断是否含有child单词,用/\bchild\b/ 判断是否有一个独立的单词
    \B匹配非单词边界。单词左右两边没有空白字符
    \0查找 NULL 字符。
    \n查找换行符。
    \f查找换页符。
    \r查找回车符。
    \t查找制表符。
    \v查找垂直制表符。
    \xxx查找以八进制数 xxx 规定的字符。
    \xdd查找以十六进制数 dd 规定的字符。
    \uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符。

    注意:

    • 在正则表达式中\表示转义字符,但是js中任何地方\都是转义字符,所以要验证\也必须输入两个(字面量中) **如:**正则表达式.表示任意字符/./只会表示是否有任意字符,如果要判断有没有.(点这个符号),需要用/\ ./来表示
    • 如果用构造函数的方法,由于它的参数是一个字符串,而\是字符串中的转义字符,如果要使用\则需要使用\ \代替(相当于用了三个\ ),这样相当于把他们先化为字面量,再自变量转换,而因为\ .其实就是.,所以没有作用
  • 量词,通过量词可以设置一个内容出现的次数用{}里面写需要的数量,量词只对它前边的一个内容起作用,

    量词描述
    n+匹配任何包含至少一个 n 的字符串。例如,/a+/ 匹配 "candy" 中的 "a","caaaaaaandy" 中所有的 "a"。
    n*匹配任何包含零个或多个 n 的字符串。例如,/bo*/ 匹配 "A ghost booooed" 中的 "boooo","A bird warbled" 中的 "b",但是不匹配 "A goat grunted"。
    n?匹配任何包含零个或一个 n 的字符串。例如,/e?le?/ 匹配 "angel" 中的 "el","angle" 中的 "le"。
    n{X}匹配包含 X 个 n 的序列的字符串。例如,/a{2}/ 不匹配 "candy," 中的 "a",但是匹配 "caandy," 中的两个 "a",且匹配 "caaandy." 中的前两个 "a"。
    n{X,}X 是一个正整数。前面的模式 n 连续出现至少 X 次时匹配。例如,/a{2,}/ 不匹配 "candy" 中的 "a",但是匹配 "caandy" 和 "caaaaaaandy." 中所有的 "a"。
    n{X,Y}X 和 Y 为正整数。前面的模式 n 连续出现至少 X 次,至多 Y 次时匹配。例如,/a{1,3}/ 不匹配 "cndy",匹配 "candy," 中的 "a","caandy," 中的两个 "a",匹配 "caaaaaaandy" 中的前面三个 "a"。注意,当匹配 "caaaaaaandy" 时,即使原始字符串拥有更多的 "a",匹配项也是 "aaa"。
    n$匹配任何结尾为 n 的字符串。
    ^n匹配任何开头为 n 的字符串。注意与[^]作对比
    ?=n匹配任何其后紧接指定字符串 n 的字符串。
    ?!n匹配任何其后没有紧接指定字符串 n 的字符串。
    var reg=/a{3}/; //表示aaa,但ab{3}只表示abbb,如果要ab一起出现3次,需要/(ab){3}/
    
    
    /*注意:这里面只要就会true正确执行,比如b{3}但是bbbb依然是正确的,因为包含了3个b*/
    

    注:在正则表达式中同时使用^ $则要求字符串必须完全符合正则表达式

    var reg1=/^a$/; //表示既要有a开头同时这个开头的a还必须是结尾
    /*上式说明只能有一个a,aaa这种是不行的,因为结尾的a不是开头的a*/
    
    var reg2=/^a|a$/; //表示以a开头或者以a结尾
    
    var reg3=/^b([0-9A-z]){0,}b$/; //表示以b开头同时以b结尾同时中间可以跟任意数字或者字母
    
  • 子集,用圆括号()包起来的属于一个整体,叫做一个子集

    //通过子集可以很轻松的实现顺序互换
    var str="abcd";//要改成"cdab"
    var reg=/(ab)(cd)/g;
    var result=str.replace(reg,"$2$1")//此时的$1和$2有特别的含有,$1代表第一个子集,$2代表第二个子集
    
    var str="111223333";
    var reg=/(/d)\1+/g;//所有相同数字分为一组
    console.log(str.match(reg))//["111","22","3333"]
    

13.3 正则断言

所谓断言,就是指明某个字符串前边或者后边,将会出现满足某种规律的字符串

在将断言前.先将子集的捕获与捕获,一般的子集通过()括住都会被捕获,这时可以通过$1等来使用被捕获的子集,而如果不想要子集被捕获,只是用做一个匹配模式,就可以让子集不被捕获到,一般是通过(?:)来括住一个子集

模式描述
(?:X)不捕获匹配,不能通过$符号进行捕获到该子集,包括下面的所有都是捕获匹配。
(?=X )零宽度正先行断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。
(?!X)零宽度负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,\w+(?!\d) 与后不跟数字的单词匹配,而不与该数字匹配 。
(?<=X)零宽度正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯。
(?<!X)零宽度负后发断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后面的 99 的实例匹配

例子:是否为浮点数

function isFloat(number){
    number=number+"";
    var reg=/^-?\d+\.\d+$/;//\.连在一起表示就是一个(.),没有其他意思
    return reg.test(number);
}
console.log(isFloat(1));//false
console.log(isFloat(1.1));//true
console.log(isFloat(1.0));//false,false是由于JS内部的储存机制,当浮点数后全是0时就被看成一个整数
console.log(isFloat("1.0"));//true,这时因为传入的就是一个1.0的字符串,所以为true

例子:手机号规则

  • 以1开头

  • 第二位3-9任意数字

  • 三位以后任意数字9位

var reg=/^1[3-9][0-9]{9}$/;

例子:邮箱格式

var reg=/^\w{3,}(.\w+)*@[A-z0-9]+(.[A-z]{2,5}{1,2}$/;

13.4 正则表达式和字符串相关的方法

正则表达式有两种用法,一种是调用自身的方法(如上面的test方法),一种是作为参数进行传递

13.4.1 split方法

split()方法中可以传递一个正则表达式作为参数来把一个字符串分割成字符串数组

注意:该方法即使不指定全局匹配的匹配模式,也会在全局进行拆分

var arr="1a2b3c4d5e6f7g";
var result=arr.split(/[A-z]/);//根据任意字母将字符串拆分
console.log(result);//[1,2,3,4,5,6,7]

13.4.2 search方法

search()可以搜索字符串中是否含有指定的内容,这个方法和indexOf()方法类似,如果搜索到了指定内容则会返回第一次出现的索引,如果没有搜索到则会返回-1,不同的是indexOf()方法并不支持正则表达式

注意:该方法即使设置全局匹配模式也只会查找出现的第一个结果

//搜索字符串中是否有abc或aec或afc
var str="abcdef"
var result=str.search(/a[bef]c/);
console.log(result);//0

13.4.3 match方法

**match()方法用做从一个字符串中将符合条件的内容提取出来,**可以用正则表达作为参数,默认情况下match只会找到第一个符合要求的内容,找到以后就会停止检索,可以设置正则表达式为g(全局匹配模式)来匹配所有的内容

var str="1a2b3c4d5e6f7A8B9C";
var result=str.match(/[a-z]/gi);//这样就能把所有的字母都提取出来
console.log(result);//[a,b,c,d,e,f,A,B,C]

/*
match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果,所以用result[0]等索引能查询到他们
如果没有匹配到就会返回null,适合用作if等判断条件
*/

13.4.4 replace方法

replace()方法可以将字符串中指定内容替换为新的内容

该方法有两个参数,第一个是被替换的内容,第二个参数是要替换的新的内容,默认只会替换查找到的第一个结果,所以可以加g进行全局匹配

var str="1a2b3c4d5e";
var result1=str.replace(/[a-z]/gi,"@-@");//把所有字母都替换为@-@
var result2=str.replace(/[a-z]/gi,"");//去除所有字母(把所有字母都替换为空串)

var result3=str.replace(/^\s*|\s*$/gm,"");//去除开头或结尾的空格

不用replace方法实现替换字符串的内容

//运用数组的join方法和字符串的spilt方法
var arr="1a2a3a4a5a";
var result=arr.spilt("a").join("b");
console.log(result);//"1b2b3b4b5b"