正则,看这篇就够了

531 阅读3分钟

一、 string会用可以用到正则的方法

  1. match 匹配,可以按照正则
  2. search 匹配的位置 没匹配到 返回 -1
  3. split 可以按照正则 拆
  4. replace 替换,可以按照正则 str.replace(reg,'b')

二、 正则的创建方法

  • 第一种 创建方法
const reg = /ab/g
const str = 'abcabbaab'
reg.test(str)
// 字符串 match 方法,获取 匹配的字符串
const strArr = str.match(reg) // [ 'ab', 'ab', 'ab' ]
  • 第二种创建方法
const reg1 = new RegExp('abc', 'i')
console.log(reg1.test('abcd')) // ture

三、常用匹配规则

  • 修饰符:** i 忽视大小写; g 全局匹配;m 执行多行匹配**
  • /^ 放到前面表示开始, [^] ^放里面 表示 非
// m 多行匹配 
const reg2 = /^a/gm
const str2 = 'abcde\na'
console.log(str2.match(reg2)) //[ 'a', 'a' ]
// 一个 []代表一位 
const reg3 = /[^a][^b]/g
const str3 = 'ab1cd'
console.log(str3.match(reg3)) //[ 'b1', 'cd' ]
  • \t 制表符;\n 换行符 空格;\r 回车符 行结束;\v 垂直制表符;\t 缩进;
  • \w === [0-9A-z_]; \W ===[^\w]
  • \d ===[0-9]; \D ===[^\d]
  • \s === [\t\n\r\v\f ]; \S ===[^\s] 空白字符 \s包含空格
  • \b === 单次边界; \B === 非单次边界
  • . === [^\r\n]匹配一位
  • \b === 单词边界; \B === 非单词边界
const reg5 = /\bcde\b/g
const str5 = 'abc cde fgh'
console.log(str5.match(reg5)) //[ 'cde' ]
// 匹配 \t
const reg6 = /\tc/g
const str6 = 'abc\tcdefgh'
console.log(str6.match(reg6)) //[ '\tc' ]
  • 个数 n* === {0,}
  • n+=== {1,}
  • n?==={0,1}
  • {X}个=== X个;
  • n{X,Y} {X,Y}个 X-Y个, 贪婪匹配原则, 能 先 Y个,后X个
// n* {0,}个 会匹配到空 串
const reg7 = /\d*/g
const str7 = 'abc'
console.log(str7.match(reg7)) // [ '', '', '', '' ]
const reg8 = /\w*/g
const str8 = 'abc'
console.log(str8.match(reg8)) // [ 'abc', '' ]

// n+ {1,}个 不会匹配到 空串
const reg9 = /\d+/g
const str9 = 'abc'
console.log(str9.match(reg9)) // null

// n? {0,1}个
const reg10 = /\w?/g
const str10 = 'aaaa'
console.log(str10.match(reg10)) // [ 'a', 'a', 'a', 'a', '' ]

// n{X} {X}个 X个
const reg11 = /\w{3}/g
const str11 = 'aaaaaa'
console.log(str11.match(reg11)) // [ 'aaa', 'aaa' ]
// n{X,Y} {X,Y}个 X-Y个, 贪婪匹配原则, 能 先 Y个,后X个
const reg12 = /\w{2,4}/g
const str12 = 'aaaaaa'
console.log(str12.match(reg12)) // [ 'aaaa', 'aa' ]

// 检验一个字符串 首尾是否含有数字
const reg13 = /^\d|\d$/g
// 检验一个字符串首尾 都  是否含有数字
const reg14 = /^\d[\s\S]*\d$/g
  • exec 正则g修饰符 lastIndex 会返回捕获()里面的
  • 非全局匹配模式下,此函数的作用和match()函数是一样的
const reg15 = /ab/g
const str15 = 'abab'
console.log(reg15.lastIndex) // 0
console.log(reg15.exec(str15)) // [ 'ab', index: 0, input: 'abab', groups: undefined ]
console.log(reg15.lastIndex) // 2
console.log(reg15.exec(str15)) // [ 'ab', index: 2, input: 'abab', groups: undefined ]

const str5 =
  'IT面试题博客中包含很多<a href="http://hi.baidu.com/mianshiti/blog/category/微软面试题">微软面试题</a>'
const exg5 = /<a.*href="(.*)".*>/g
console.log(exg5.exec(str5))
// [
//   '<a href="http://hi.baidu.com/mianshiti/blog/category/微软面试题">微软面试题</a>',
//   'http://hi.baidu.com/mianshiti/blog/category/微软面试题',
//   index: 12,
//   input: 'IT面试题博客中包含很多<a href="http://hi.baidu.com/mianshiti/blog/category/微软面试题">微软面试题</a>',    
//   groups: undefined
// ]
  • ()或者,捕获, (?:)不捕获; match replace
// () 里面 或者的关系
const reg4 = /(abc|bcd)[0-9]/g
const str4 = 'bcd1'
console.log(str4.match(reg4)) //[ 'bcd1' ]
// () 反向引用
const reg16 = /(\w)\1\1\1/g
const str16 = 'aaaabbbb'
console.log(str16.match(reg16)) //[ 'aaaa', 'bbbb' ]
// \w 匹配数字字母_ ,
// \1对应的匹配第一个表达式(\w), \2匹配第二个表达式(\w) g是全局匹配
const reg17 = /(\w)\1\1(\w)\2\2/g
const str17 = 'aaabbbaaabbb'
console.log(str17.match(reg17)) // [ 'aaabbb', 'aaabbb' ]

console.log(reg17.exec(str17)) //['aaabbb','a','b',index: 0,input: 'aaabbbaaabbb',groups: undefined]
console.log(reg17.exec(str17)) //['aaabbb','a','b',index: 6,input: 'aaabbbaaabbb',groups: undefined]
console.log(reg17.exec(str17)) //null
  • 两道经典例题:
// aabb ===>bbaa
// $1第一个表达式的值  $2第二个表达式的值
const reg18 = /(\w)\1(\w)\2/g
const str18 = 'aabb'
console.log(str18.replace(reg18, '$2$2$1$1')) // bbaa
console.log(
  'str18,fun: ',
  str18.replace(reg18, function ($, $1, $2) {
    return $2 + $2 + $1 + $1
  })
)

// the-first-name ===> theFirstName
const reg19 = /-(\w)/g
const str19 = 'the-first-name'
console.log(
  'str19: ',
  str19.replace(reg19, function ($, $1) { // $ 第一个是 匹配的正则的,第二个 是 捕获的
    return $1.toUpperCase()
  })
)
  • (?=b)正向预查;(?<=b)反向预查; (?!b)正向断言; (?:)不捕获 (?:pattern) 匹配得到的结果包含pattern,(?=pattern) 则不包含
// n? {0,1}个 const reg10 = /\w?/g   
// 正向预查,正向断言
// const reg20 = /a(?=b)/g // a 后面有b [ 'a','a' ]
//const reg20 = /a(?!b)/g // a 后面没有b  [ 'a', 'a', 'a' ]
//const reg20 = /(?<=b)a/g; // a 前面有b  [ 'a' ]
const reg20 = /(?<!b)a/g; // a 前面没有b  ['a', 'a', 'a', 'a']
const str20 = 'abaaaab'
console.log(str20.match(reg20)) 

const data = 'windows 98 is ok';
data.match(/windows (?=\d+)/);  // ["windows "]
data.match(/windows (?:\d+)/);  // ["windows 98"]
data.match(/windows (\d+)/);    // ["windows 98", "98"]
  • 贪婪匹配 后面 加?,变成非贪婪匹配
// const reg21 = /a+/g // [ 'aaa' ]
// const reg21 = /a+?/g // [ 'a', 'a', 'a' ]
const reg21 = /a??/g // [ '', '', '', '' ]
const str21 = 'aaa'
console.log(str21.match(reg21))

const reg3 = /<.+?>/g
const str3 = 'ada<option value="hh">0</option>54<div id="as">adda</div>ad'
console.log(str3.match(reg3)) // [ '<option value="hh">', '</option>', '<div id="as">', '</div>' ]
  • 经典例题:
// '10000000000' 3的倍数 (\d{3})+  边界匹配,匹配 边界后面有三个数的边界
// 然后用,替换
const cestr1 = '10000000'
const cereg1 = /\B(?=(\d{3})+$)/g
console.log('cestr1: ', cestr1.replace(cereg1, ',')) //1,000,000

const cereg2 = /(\B(?=(\d{3})+(?!\d))/g
console.log('cestr1: ', cestr1.replace(cereg2, ',')) //1,000,000

// (?<a>) 是分组,给了组名 匹配 aabc 类型
// const reg11 = /(?<a>.)\k<a>(?!\k<a>)(?<b>.)(?!\k<b>|\k<a>)./g
const reg11 = /(.)\1(?!\1)(.)(?!\1|\2)./g
const str11 = '涛涛不觉'
console.log('str11: ', str11.match(reg11)) // [ '涛涛不觉' ]