正则表达式基本用法

李胜
• 阅读 3740

基本语法

  • 单个字符

    数字: \d  等价于 [0-9]
    数字或字母(下划线): \w  等价于 [A-Za-z0-9_]
    非数字和字母(下划线):\W 等价于 [^A-Za-z0-9_]
    空格和tab:\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\n\r\t\v]
    非空格和tab:\S  匹配任何非空白字符。等价于 [^\f\n\r\t\v]
    任何字符: 点号 . ,匹配除换行符\n, \r之外的任何字符
  • 数量

    0或多次: 星号 * ,等价于{0,}
    0或者1个: 问号 ? ,匹配前面的子表达式0或1次,等价于 {0,1}
    1或者更多:加号 + ,匹配 前面的子表达式1次或多次,等价于 {1,}
    出现n次: {n}
    出现至少n次: {n,}
    最少n次,最多m次: {n,m}
  • 位置:行开头,行结尾,单词的结界

    行开头: 上尖角符号 ^ 
    行结尾: 美元符号 $
    单词的结界: \b,匹配的是单词和空格间的位置

字符分类(中括号符号[])

  • 基本用法:

    中括号 []表示或逻辑,比如[abc]表示a或者b或者c,在方括号里,特殊字符是不需要转义的

  • 特殊语法:-,^.

    • -是第一个字符时,表示它本身,放在中间是表示区间。比如[a-z]表示从a到z
    • ^放在外面表示一行的开头^放在[]里面,表示取反。比如 [^ab],表示不是a且不是b。点符号.[]里不需要转义,就是点号本身;在外面直接使用表示匹配任何字符;在外面表示点号本身,需要转义 \.
  • ()[]一样,也可以用于或语法,比如,(a|b)的意思是a或者b

分组捕获

  • 匹配到的组。

    比如/\d{3}-(\d{3})-(\d{4})/ 匹配 “212-555-1234” 时。

    Group0是"212-555-1234"

    Group1是第一个括号555

    Group2是第二个括号1234

  • 选择分组。

    方法一:使用$符,$1表示555$2表示1234

    方法二: 使用反斜杠\\1表示555\2表示1234

  • 美元符$和反斜杠\的区别:

    $ 是在替换的时候进行标志或选择。但是对于表达式本身,用\ 。这句话的意思是,对于正则表达式本身,用反斜杠\加数字来匹配子项。例如: 匹配字符串语句中重复出现的单词。

    reg = /\b(\w+)\s\1\b/
    let str = "This is is some text. How old the the dog dog is?"
    // 匹配到的结果是: is is、 the the 和 dog dog

JavaScript的string中的应用

  • reg.test(): 正则表达式自身的test方法,是否包含,包含返回true,不包含返回false reg.test(str)

    let reg = /\d{3}/
    let str = "abc123"
    reg.test(str) // true
  • str.match(reg): 正则表达式,返回的结果与两个因素相关:g修饰符; 是否有分组。

    • 无g修饰符,且无分组时,返回的是第一个匹配到的字符串

      let reg = /\w+/
      let str = "joy, I know something about you."
      let value = str.match(reg)
      // ["joy", index: 0, input: "joy, I know something about you.", groups: undefined]
    • 有g修饰符,无分组时,返回所有匹配到的字符串,不含分组

      let reg = /\w+/g
      let str = "joy, I know something about you."
      let value = str.match(reg)
      // ["joy", "I", "know", "something", "about", "you"]
    • 无g修饰符, 有分组时,返回的是第一个匹配到的字符串和它的分组

      let reg = /(\d{3})[-.](\d{4})/
      let str = "These are two Phone Numbers 212-2345 and 211-3234"
      let value = str.match(reg)
      // ["212-2345", "212", "2345", index: 28, input: "These are two Phone Numbers 212-2345 and 211-32344", groups: undefined]
    • 有g修饰符,有分组时,返回的是匹配所有字符串,不含分组

      let reg = /(\d{3})[-.]\d{4}/g
      let str = "These are two Phone Numbers 212-2345 and 211-3234"
      let value = str.match(reg)
      // ["212-2345", "211-3234"]
      // 比照无分组有g时的结果,可以发现,有无分组时,结果完全相同
  • reg.exec()方法 : 每执行一次,返回匹配序列和其子项的数组。直到返回的是null。如果返回nall后,还继续执行,将会从字符串开头重新执行一次(亲测如此)

    还是以电话号码为例:

    有g修饰符,有分组

    let reg = /(\d{3})[-.]\d{4}/g
    let str = "These are two Phone Numbers 212-2345 and 211-3234"
    reg.exec(str) // ["212-2345", "212", index: 28, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    reg.exec(str) // ["211-3234", "211", index: 41, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    reg.exec(str) // null
    reg.exec(str) // ["212-2345", "212", index: 28, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]

    无g修饰符,有分组

    let reg = /(\d{3})[-.]\d{4}/
    let str = "These are two Phone Numbers 212-2345 and 211-3234"
    reg.exec(str)  // ["212-2345", "212", index: 28, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    // 不管执行多少次,执行结果都一样,输出第一个匹配到的字符串和它的子项

    有g修饰符,无分组

    let reg = /\d{3}[-.]\d{4}/g
    let str = "These are two Phone Numbers 212-2345 and 211-3234"
    reg.exec(str) // ["212-2345", index: 28, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    reg.exec(str) // ["211-3234", index: 41, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    reg.exec(str) // null
    reg.exec(str) // ["212-2345", index: 28, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    // 和有g修饰符,有分组的区别只是结果里没有分组的内容输出

    无g修饰符,无分组

    let reg = /\d{3}[-.]\d{4}/
    let str = "These are two Phone Numbers 212-2345 and 211-3234"
    reg.exec(str) // ["212-2345", index: 28, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    reg.exec(str) // ["212-2345", index: 28, input: "These are two Phone Numbers 212-2345 and 211-3234", groups: undefined]
    // 不管执行多少次,执行结果都一样,和无g修饰符,有分组的区别只是结果里没有分组的内容输出

    下面是一个有分组、无g修饰符的例子

    let str = "{{name}}"
    let reg = /\{\{(.*)\}\}/
    reg.exec(str) 
    // 不管执行多少次,得到的结果永远是: ["{{name}}", "name", index: 0, input: "{{name}}", groups: undefined]
  • str.split()方法

    split的参数除了是字符串,也可以是正则表达式

    // 将一段话按照连续的空格和逗号拆开
    let str = "how are you, I am here"
    let arr = str.split(/[\s,]+/)
    // ["how", "are", "you", "I", "am", "here"]
  • str.replace(reg, replaceStr|function)方法

    第一个参数是正则表达式,是匹配的内容,第二个参数是替换的字符串或回调函数。

    1. 不会修改原字符串,只会返回修改后的字符串;

      let reg = /\ba(\w+)\b/g
      let str = "how are you, I am here"
      // 将a开头的单词,去掉,后面单词重复
      let newStr = str.replace(reg, "$1-$1")  // 子项是在正则表达式外,用反斜杠的话得到的将不是希望的结果
      // newStr : how re-re you, I m-m here
      // str: how are you, I am here

      在用replace的时候,replaceStr是字符串,用 $加数字的方式匹配子项,注意第一个子项是1,不是0,第0个是 reg 匹配到的完整序列

    2. 正则reg如果没有用g,和match一样,只会替换第一个

      let reg = /\ba(\w+)\b/     // 没有用g修饰符,newStr只会匹配第一个a开头的单词are,am没有匹配到
      let str = "how are you, I am here"
      // 将a开头的单词,去掉,后面单词重复
      let newStr = str.replace(reg, "$1-$1")
      // how re-re you, I am here
    3. function(match,group1,index,str)

      参数:function的参数个数是不固定的。

       1,回调函数的第一个参数是匹配到的内容
       2,(如果进行分组匹配了 )后面的参数依次是子项1,子项2(一直到子项n)
       3,然后是 匹配到的字符串对应的索引位置
       4,最后是 原始字符串。所以,function的参数个数是不固定的。

      返回值:

       let reg = /\ba(\w+)\b/g
       let str = "how are you, I am here"
       let newStr = str.replace(reg, (p1,p2,p3,p4) => {
         // 当只有1个子项时,replace的回调函数有四个参数: 匹配的字符串、子项1,子项的index,str
         return p1.toUpperCase()
       })

练习:

  1. 匹配电话号码

     915-134-3122   
     643.123.3355  
     (120)867-5509

    分析:数字一共是10位,数字中间夹杂着点号 . , 短线- 和 括号 ()

    let str = "643.123.3355"
    let reg = /^\(?\d{3}[-.)]\d{3}[-.]\d{4}/
    let result = reg.test(str)  // true
  2. .net,.edu,.com结尾的邮箱

    xiaokeke@126.com  
    ytxwz@google.net 
    gg.s.ddy@sjtu.edu

    分析:邮箱是数字或字母\w开头,接@,然后继续数字或字母 \w,然后.net等结尾。

    let reg = /^\w[\w.]+@\w+\.(edu|net|com)/
    let str = "gg.sd.dy@sjtu.edu"
    let result = reg.test(str)  // true
  3. 有个名单列表,名和姓是反的,交换过来

    shiffina, Danial
    shifafl, Danial
    shquer, Danny

    分析:交换过来,就是对str做替换操作

    分两步:正则匹配到姓、名、姓名中间的部分; replace方法调换子项的顺序

    let str = "shiffina, Danial"
    let reg = /\b(\w+)([,\s]+)(\w+)\b/g
    let newStr = str.replace(reg, '$3$2$1')
  4. 匹配markdown中的link标签,替换为html标签

    [google](http://google.com)
    [itp](http://itp.nyu.edu)
    [Coding Rainbow](http://codingrainbow.com)

    分析:把方括号[]里的字符串找出来,作为a标签之间的内容。把括号 () 中的字符串找出来,作为a的href标签的内容。

    match方法实现

    let str = "[itp](http://itp.nyu.edu)"
    let reg = /\[(\w+)\]\((http:\/\/[\w.]+\.\w+)\)/
    let result = str.match(reg)
    let html = ""
    if(result && Array.isArray(result)){
      let [,name, hrefData] = result
      html =  `<a href=${hrefData}>${name}</a>`  
    }
    // html:  <a href=http://itp.nyu.edu>itp</a>

    replace方法实现

    由计算的结果可知

    • replaceFunction的返回值会替换掉匹配到的字符串totalStr
    • regg时,会匹配整个字符串;不加g,只会匹配第一个字符串

      let str = "这是百度的地址:[baidu](http://www.baidu.com), 我经常访问这个网站。同时,我也经常去[taobao](http://www.taobao.com)"
      let reg = /\[(\w+)\]\((http:\/\/[\w.]+\.\w+)\)/g
      let newStr =  str.replace(reg, (totalStr, name, address) => {
        return `<a href=${address}>${name}</a>`
      })
      // 这是百度的地址:<a href=http://www.baidu.com>baidu</a>, 我经常访问这个网站。同时,我也经常去<a href=http://www.taobao.com>taobao</a>
      // 如果reg没有g修饰符: 这是百度的地址:<a href=http://www.baidu.com>baidu</a>, 我经常访问这个网站。同时,我也经常去[taobao](http://www.taobao.com)
  5. 匹配连续序列

    This is is a dog dog under the tree tree, do you know?

    匹配其中的is is, dog dog, tree tree

    let str = "This is is a dog dog under the tree tree, do you know?"
    let reg = /\b(\w+)\b\s+\1/g
    let result = str.match(reg)   // [ 'is is', 'dog dog', 'tree tree']

    matchg修饰符时,返回的是匹配出来的所有字符串。

  6. 提取英文单词,存到数组

     "unicorns and rainbows And, Cupcakes"

    match方法:

    let str =  "unicorns and rainbows And, Cupcakes"
    let reg = /\w+/g
    let result = str.match(reg)
    // [ 'unicorns', 'and', 'rainbows', 'And', 'Cupcakes' ]

    split 方法:

    let str =  "unicorns and rainbows And, Cupcakes"
    let reg = /[\s,]+/g
    let result = str.split(reg)
    // [ 'unicorns', 'and', 'rainbows', 'And', 'Cupcakes' ]
  7. 将下列句子中aeiou替换成大写字母

    how old are you .
    let str = "how old are you ."
    let reg = /([aeiou])/g
    let result = str.replace(reg, (p1, p2) => {
      return p2.toUpperCase()
    })
    // hOw Old ArE yOU .
  8. 练习题4的扩展

    方括号和圆括号中的内容不限定死,可以是任意形式,比如中文。怎么匹配呢?

    用点号 .和星号 *一起。但是由于点号是贪婪匹配\[(.*)\]会把整个str都匹配出来,因此不能使用贪婪匹配。将问号放在数量的后面,可去掉贪婪属性。

    let str = "[百度](http://www.baidu.com)[baidu]" 
    let reg = /\[(.*?)\]\((.*?)\)\[.*?\]/
    let result = str.replace(reg, `<a href='$2'>$1</a>`)
    // <a href='http://www.baidu.com'>百度</a>

    懒惰限定符如下:
    正则表达式基本用法

点赞
收藏
评论区
推荐文章
Kubrnete Kubrnete
5年前
Python正则表达式
re正则表达式基础语法|表达式|可匹配|表达式|可匹配|||||||\r,\n|代表回车和换行符|\^|可匹配^本身||\t|制表符|\$|匹配$符号本身||\\|代表“\”本身|\.|匹配小数点“.”本身||表达式|可匹配|||||\d|任意一个数字,09中的任意一个||\
Wesley13 Wesley13
4年前
java循环语句与数组学习
赋值运算符的基本用法赋值运算符有哪些:,,,,/,%a1等价于aa1,同理注意事项:1.基本的赋值运算符:把右边的数据赋值给左边。2.扩展的赋值运算符:,,,/,%举例说明
执键写春秋 执键写春秋
4年前
Java练习(一)——对字符串中的字符进行统计
题目:输入一行字符,分别统计出其中文、英文字母、空格、数字和其它字符的个数。packagetest;importjava.util.Scanner;publicclassPratice1publicstaticvoidmain(Stringargs)//TODOAutogeneratedmethodstubint
Wesley13 Wesley13
4年前
C语言概述
C语言基本语法单位字符集字符是高级语言中的最小单位,是构成语法单位的基础。C语言中规定可以使用的合法字符的集合为C字符集C字符集采用ASCII码字符集C语言字符集由下列字符组成(1)字母和数字字符。(小写字母a~z、大写字母A~Z、数字0~9)(2)不可打印的字符。(空格符、回车符、换行符、控
Stella981 Stella981
4年前
Python学习笔记(一)
一、变量和简单数据类型(一)变量变量的命名和使用变量名只能包含字母、数字和下划线。不能以数字开头。变量名不能包含空格,用下划线。不要将Python关键字和函数名用作变量名。要简短、具有描述性。小写字母l和数字1,大写字母O
Wesley13 Wesley13
4年前
Python学习笔记(一)基础语法
Python标识符在python里,标识符有字母、数字、下划线组成。在python中,所有标识符可以包括英文、数字以及下划线(\_),但不能以数字开头。python中的标识符是区分大小写的。以下划线开头的标识符是有特殊意义的。以单下划线开头(\_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用"fro
Stella981 Stella981
4年前
201771010117马兴德 实验二 Java基本程序设计(1)
实验二Java基本程序设计(1)第一部分理论知识的学习。第三章Java基本程序设计结构1 基本知识:(1)标识符:标识符由字母、下划线、美元符号和数字组成,且第一个符号不能为数字。比如Hello,$1234都是合法的字符;同时标识符也可用作类名、变量名、方法名、文件名等。    (2)关
Stella981 Stella981
4年前
AJPFX总结关于Java中过滤出字母、数字和中文的正则表达式
1、Java中过滤出字母、数字和中文的正则表达式(1)过滤出字母的正则表达式\^(AZaz)\(2)过滤出数字的正则表达式\^(09)\(3)过滤出中文的正则表达式\^(\\\\u4e00\\\\u9fa5)\(4)过滤出字母、数字和中文的正则表达式\^(azAZ09\\\\u
Stella981 Stella981
4年前
PostgreSQL使用建议
一、命名规范1. DB object: database, schema, table, view, index, function, trigger等名称(1) 建议使用小写字母、数字、下划线的组合(2) 建议不使用双引号即"包围,除非必须包含大写字母或空格等特殊字符(3) 长度不能超过63个字符(4) 禁止使用SQ
可莉 可莉
4年前
201771010117马兴德 实验二 Java基本程序设计(1)
实验二Java基本程序设计(1)第一部分理论知识的学习。第三章Java基本程序设计结构1 基本知识:(1)标识符:标识符由字母、下划线、美元符号和数字组成,且第一个符号不能为数字。比如Hello,$1234都是合法的字符;同时标识符也可用作类名、变量名、方法名、文件名等。    (2)关
Stella981 Stella981
4年前
Scala_标识符
用于对象,类,变量和方法的名称称为标识符。关键字不能用作标识符,标识符区分大小写。类名首字母大写方法名称第一个字母小写程序文件名应该与对象名称完全匹配1.字母数字标识符以字母或下划线开头,后跟字母、数字或下划线。$字符是Scala中的保留关键字,不应在标识符中使用2.运算符标识符由一个或