一片两片三四片、落尽正则全不见

342 阅读12分钟

前文

转义字符 \

  • 如果普通字符串本身是双引号,那么字符串中就不能存在多的一个双引号,只能使用单引号代替
    • "12'343"
  • 使用\转义字符可以代替
    • "123"123"
  • 如果在字符串中存在",那么转义字符串后面的东西就会强制转换成文本
let str = "123"456"
  • 如果想字符串本身上存在 \ ,那么就需要再使用转义符号转义 \, 因为\本身意义就是转义的,所以不能单独使用
let str = "123\456"

转义字符串换行 \n

  • 使用 转义字符串 \n 将字符串变为多行
let str = "1\n1"

结束符/r

  • 正常电脑按一个回车键,在系统的底层识别的就是\r\n,linux系统中回车只有\n
let str = '11212\r' //达标此行结束 在console.log()中是看不出来的

缩进 \t

  • 字符串的缩进,相当于键盘中的tab按键
let str = '1111\t111'

正则表达式创建

正则表达式字面量 RegExp

  • let reg = /'内容'/

构造创建

  • let reg = new RegExp('内容')

正则表达式测试方法.test() 返回布尔值

// 创建一个abc相连的正则
let reg = /abc/ 
// 测试abcd中是否存在reg中的字符 返回布尔值
reg.test("abcd")  // true

String.match在字符串内检索指定的值,或找到一个或多个正则表达式的匹配

  • 该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置

修饰符

  • 在正则表达式最后的/后面添加属性
  • /abc/属性

i : ignoreCase 忽略大小写

  • 使用i属性后那么匹配时将忽略匹配值的大小写
let str = /abc/
// 使用大写ABC测试将不会通过,必须是要求和正则相同的,多字符少字符无所谓,但必须有相同的
str.test('ABC') // false

let str = /abc/i
str.test('ABC') // true

g :global 所有的

  • 使用g属性后那么匹配时将匹配所有的正则
// 查找str中是否存在多个abc
let reg = /abc/g
let str = 'abcabcabc'
str.match(reg) // ['abc', 'abc', 'abc']

^ : 以固定格式开头

  • 开头修饰符,在正则表达式第一个/后面增加
  • 使用^属性后那么匹配时将匹配所有的正则
// 查找str中是否存在以a开头的字符串
let reg = /^a/g
let str = 'abca'
str.match(reg) // ['a']

m :多行匹配

  • 使用m匹配多行正则,需要搭配修饰符 g
// 创建一个全部的,多行的,以a开头的正则
let reg = /^a/gm
let str = 'abc\na'
str.match(reg) //  ['a', 'a']

语法[]方括号表达式

[]方括号表达式介绍

  • 在正则表达式中[]一个方括号代表一位
    • /123/ 三位 == /[] [] []/
  • 每一个方括号中都可以填写指定的范围
  • 示例
    • /[1234567890]/
    • 匹配是否存在一位取值范围0-9的数字
    • /[1234567890]/.test('1') true
    • /[1234567890]/.test('a') false
// 创建一个全局匹配三个0-9数字相连的正则
let reg = /[1234567890][1234567890][1234567890]/g

let str = '1234jj235'
str.match(reg) //  ['123', '235']
// 创建一个全局匹配ab-cd-d三个字母相连的正则
let reg = /[ab][cd][d]/g
let str = 'abcd'
str.match(reg) // ["bcd"]
// 创建一全局匹配0-9或A-z+cd+d三个数字或字母相连的正则
let reg = /[0-9A-z][cd][d]/g

let str = '1cd2ddAAA'
str.match(reg) // ['1cd', '2dd']

[]方括号中的^代表非

  • 在方括号表达中使用^代表非,除了
  • 示例
    • /[^a][b][c]/
    • 代表第一位除了a都可以第二位则是b第三位则是c相连的字母
let reg = /[^a][b][c]/g

let str = 'abcbbcAbc'

str.match(reg) // [bbc,Abc]

()圆括号表达式

  • 只使用()相当于数学中的()优先计算:
  • 还有一个意思是子表达式下面会介绍
let reg = /(a)/g

let str = 'abcbbcAbc'

str.match(reg) // [a]

let reg = /(a)[b]/g

let str = 'abcbbcAbc'

str.match(reg) // ['ab']

()圆括号中的 | 或

  • 跟js中的||操作符相同
  • 示例
  • /(abc|bcd)/g
    • 代表只能匹配abc或bcd
let reg = /(abc|bcd)/g

reg.test('abc') // true
reg.test('bcd') // true
reg.test('bddd') // false
// 创建一个匹配全局第一位是abc或bcd并且第二位是0-9之间相连的两个字符串
let reg = /(abc|bcd)[0-9]/g

reg.test('abc1') // true
reg.test('bcdA') // false

元字符

\w:world 代表一位 == [0-9A-z_]

  • \w元字符代表一位0-9A-z和_的集合
// 创建一个全局第一位0-9A-z_之间第二位c第三位d相连的三个字符串
let reg = /\wcd/g

let str = '1dccd'

str.match(reg) // ['ccd']

\W:代表一位和\w相反 == [^\w]

  • \W元字符代表一位和\w相反的字符串
// 创建一个全局第一位不是0-9A-z_之间的第二位d第三位c相连的三个字符串
let reg = /\Wdc/g

let str = '1dccd*dc'

str.match(reg) // [*dc]

\d:代表一位[0-9]

  • \d元字符代表一位0-9之间的数字
// 创建一个全局第一位匹配0-9之间的数字,
// 第二位0-9、A-z_之间的字符串第三个为d第四个为e的字符串
let reg = /\d\wde/g

let str = '00de0ede00ed'

str.match(reg) // [00de] [0ede]

\D:代表一位和\d相反 == [^0-9]

  • \D元字符代表一位不是0-9之间的字符串
// 创建一个全局第一位匹配不是0-9之间的数字,
//  第二位0-9、A-z_之间的字符串第三个为d第四个为e的字符串
let reg = /\D\wde/g

let str = '00deede00ed'

str.match(reg) // [eede] 

表达式中也可以使用元字符

  • 表达式中也可以使用元字符
// 创建一个全局包含0-9和A-z_的正则
let reg = /[\w]/g

let str = '123asd'

str.match(reg) // ['1', '2', '3', 'a', 's', 'd']

// 创建一个全局第一位0-9A-z_之间的字符串
// 第二个为不是0-9A-z_之间的字符串
// 第三个为0-9之间的字符串
// 第四个为不是0-9之间的字符串
let reg = /[\w][\W][\d][\D]/g

let str = '0*1S0000'

str.match(reg)

\s :代表一位任何空白字符,包括空格、制表符、换页符等等。==[ \f\n\r\t\v]

// 创建一个全局匹配有空白字符的字符串
let reg = /\s/g

let str = '\r123 \n'

str.match(reg) //  ['\r', ' ', '\n']

// 还可以搭配replace使用

'\r b \n'.replace(/\s/g, '') // 'b'

\S : 代表一位任何非空白字符。等价于 [^ \s]

// 创建一个全局匹配没有空白字符的字符串
let reg = /\S/g

let str = '\r123 \n'

str.match(reg) // ['1', '2', '3']

\b :代表一位 单词边界 也就是指单词和空格间的位置。

  • 例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
// 创建一个全局头单词边界是er的
let reg = /\ber\b/g

let str = 'eredsd ersdfsdf'

str.match(reg) // [er] [er]

// 创建一个全局头尾单词边界都是er的
let reg = /\ber\b/g

let str = 'eredsd er sdfsdf'

str.match(reg) // [er]

\B : 代表一位 非单词边界

// 创建一个头有单词边界尾没有单词边界的er

let reg = /\ber\B/g

let str = 'eredsd ersdfsdf'

str.match(reg) // [er] [er]

// 创建一个有尾单词边界没有头单词边界的ed
let reg = /\Bed\b/g

let str = 'eredsded sdfsdf'

str.match(reg) // [ed]

. :代表一位 == [^\r\n]

  • 代表除了\r\n全部匹配
let reg = /./g

let str = '\rn\n 12233'

str.match(reg) //['n', ' ', '1', '2', '2', '3', '3']

量词:n可以代表任何东西

n+ : 匹配任何包含出现1次至无数次的字符串 {1, Infinity(正无穷)}

// 创建一个全局[0-9A-z_]之间的一位可以出现1次到无数次
let reg = /\w+/g

let str = 'abc'

str.match(reg) // [abc]
  • n+会采用贪婪匹配原则,能多的绝对不会少
let reg = /\w+/g

let str = 'aaaaaaaaaaaaabbbccc'

str.match(reg) // ['aaaaaaaaaaaaabbbccc']

n* : 匹配任何包含出现0次至无数次的字符串 {0, Infinity(正无穷)}

// 创建一个全局[0-9A-z_]之间的一位可以出现0次到无数次
let reg = /\w*/g

let str = 'abc'

str.match(reg) // ['abc', '']
  • 为什么会有空串的存在?
  • 的查找规则先查看abc符不符合要求,如果符合要求此时就是3
  • 然后会/g全局匹配,*可以匹配0个或多个
  • abc中的c后面还存在空,所以查找的时候会查找一个空串出来
// 创建一个全局匹配[0-9]之间的一位可以出现0次到无数次
let reg = /\d*/g

let str = 'abc'

str.match(reg) // ["","","",""]

n? :匹配任何包含0次或1次的字符串 {0,1}

// 创建一个全局[0-9A-z_]之间的一位可以出现0次到1次
let reg = /\w?/g

let str = '111a'

str.match(reg) // ['1', '1', '1', 'a', '']

n{x} :匹配包含x个n的序列的字符串 x可以自定义 {x}

// 创建一个全局匹配[0-9]之间一位可以包含长度11位的数字
let reg = /\d{11}/g

let str = '18211896634'  // 11位

str.match(reg) // ['18211896634']

// 给与一个数字到11位但存在字母的情况
let reg = /\d{11}/g

let str = '182a11896634'  // 11位

str.match(reg) // null 没有匹配到

// 直接匹配全部是数字并且是11位的
/\d{11}/.test('18211896634')

n{x,y} :匹配包含x个到y个的字符串,x,y可以自定义{x,y}

  • 匹配规则
  • 首先根据贪婪匹配原则匹配,如果没有达到y的长度,则自己缩短到最小x的数
// 创建一个全局匹配[0-9]的一位可以包含长度3-5的数字
let reg = /\d{3,5}/g

let str = '123451234' // 9位

str.match(reg) // ['12345', '1234']

// 6位数字
let reg = /\d{3,5}/g

let str = '123451' // 6位

str.match(reg) //['12345']
  • 如果没有设置y的话则默认y为正无穷 {0, Infinity(正无穷)}
let reg = /\d{3,}/g

let str = '123451' // 6位

str.match(reg) //['123451']

n$ :匹配结尾必须为n的字符串

// 创建一个全局匹配必须为[0-9]之间结尾的数字
/\d$/.test('1111A') //false

/\d$/.test('AAAAA1') //true

^n :匹配开头必须为n的字符串

// 创建一个全局匹配必须为[0-9]之间开头的数字
/^\d/g.test('1111A') //true

/^\d/g.test('AAAAA1') //false

// 以数字开头,以数字结尾
/^\d$/g.test('1')

// 因为查找的是一位,开头和结尾必须是一位0-9之间的数字
/^\d$/g.test('11111') // false
  • 可以用来匹配手机号的长度
// 创建一个以数字开头长度为11位并且结尾是数字
/^\d{11}$/.test('18211076614')

正向预查 正向断言

(?=n ) 匹配任何其后紧接指定字符串n的字符串

// 创建一个全局匹配a后面必须是b的正则
let reg = /a(?=b)/g

let str = 'abcdab'
str.match(reg) // ['a', 'a']

// 创建一个全局匹配以a开头并且a后面必须是b的正则
let reg = /^a(?=b)/g

let str = 'abcdab'
str.match(reg) // ['a']

(?!n) 匹配任何其后没有紧接指定字符串n的字符串

// 创建一个全局匹配a后边必须不是b的正则

let reg = /a(?!b)/g

let str = 'abacab'

str.match(reg) // ['a']

()子表达式

  • 正常情况下只写()没什么用也不会影响
  • 但是在特殊情况下会有不同的意思
  • /(a)/ 当使用括号括起表达式的时候,括号会记录里面的匹配内容,可以利用反向引用引用出来 \1
  • /(a)\1/ 反向引用第一个字表达式中的内容,一个括号()代表一个表达式
  • /(a)\1/ 正则解释:匹配第一位是a,第二位也是和第一位相同的字符串,也就是a
  • /(\w)\1/ :正则解释:第一位匹配规则中匹配到的字符串,第二位也会查找第一位匹配到的相同字符串
  • /(\w)\1\1\1/ : 三次引用第一个表达式中的内容
    • 例如:/(\w)\1\1\1/ :第一位符合条件的是A,第二、三、四位必须也是相同的A
// 创建一个匹配四个相同字符串的正则
let reg = /(\w)\1\1\1/g

let str = 'aaaabbbccccabcd'

str.match(reg) // ['aaaa', 'cccc']
// 创建一个匹配AABB类型的字符串
let reg = /(\w)\1(\w)\2/g

let str = 'aabbccddabcdcccc'

str.match(reg) //  ['aabb', 'ccdd', 'cccc']

正则表达式方法

exec()匹配方法,返回一个类数组

let reg = /ab/g

let str = 'abbaabab'
console.log(reg.exec(str))

//['ab', index: 0, input: 'abababab', groups: undefined]
  1. 第一次执行exec方法返回的index代表指向的第一个匹配正确字符串的指针索引
  2. 第二次执行如果匹配成功指针则指向第二个匹配正确字符串的指针索引
  1. 如果没有匹配成功则返回null,返回null之后再次执行exec方法则会从第一条开始
let reg = /ab/g

let str = 'abbaabab'
console.log(reg.exec(str)) // index 0
console.log(reg.lastIndex) // index 4
console.log(reg.exec(str)) // index 6
console.log(reg.exec(str)) // null
console.log(reg.exec(str)) // index 0
console.log(reg.exec(str)) // index 4
console.log(reg.exec(str)) // index 6

LastIndex 返回exec方法中的index

  • 和exec中的index相同
let reg = /ab/g

let str = 'abbaabab'
console.log(reg.lastIndex) // 0
console.log(reg.exec(str)) // index 0
  • 修改lastIndex
let reg = /ab/g

let str = 'abbaabab'
console.log(reg.exec(str)) // index 0
reg.lastIndex = 0;
console.log(reg.exec(str)) // index 0 
// 创建一个匹配AABB类型的字符串
let reg = /(\w)\1(\w)\2/g

let str = 'aabbccddabcdcccc'

reg.exec(str) // ['aabb', 'a', 'b', index: 0, input: 'aabbccddabcdcccc', groups: undefined]
reg.exec(str) // ['ccdd', 'c', 'd', index: 4, input: 'aabbccddabcdcccc', groups: undefined]
reg.exec(str) // ['cccc', 'c', 'c', index: 12, input: 'aabbccddabcdcccc', groups: undefined]

练习题

检验一个字符串首或尾是否含有数字

let reg = /^\d|\d$/g

let str = '123bac'

str.match(reg)// ['1']

检验一个字符串首尾是否都含有数字

let reg = /^\d[\w\W]*\d$/g

let str = '12sdf*afaa1'

str.match(reg) // [12sdf*afaa1]

reg.test(str) // true

检验一个字符串头部是否包含指定数字并且以数字到11位结尾

/^(123|134)\d{8}$/.test('12345678901') // true

贪婪匹配

  • 正则默认匹配方式为贪婪匹配,能多个匹配尽量匹配少的
  • n{x, y} 能匹配y个尽量匹配y个,底线就是x个
let reg = /a{2,5}/g

let str = 'a12aaaaaaaaa'

str.match(reg)// ['aaaaa', 'aaaa']

?非贪婪匹配,打破贪婪匹配

  • 在任何一个量词后面多写一个?问号
// 创建一个n+量词
let reg = /a+?/g

let str = 'aaaaaaaa'

str.match(reg) // ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']
// 创建一个最少3个最多5个的正则

let reg = /a{3,5}?/g

let str = 'aaaaaaaa'

str.match(reg)//['aaa', 'aaa']
// 创建一个n?量词 至少0次或多次

let reg = /a??/g

let str = 'aaaaaaa'

str.match(reg)// ['', '', '', '', '', '', '', '']