正则表达式

215 阅读3分钟

正则表达式中的字符

原义文本字符

字符代表的意思就是字符本身,没有额外的含义

元字符

有特殊含义的非字母字符

修饰符

  1. 全局匹配:g
  2. 不区分大小写:i
  3. 匹配多行文本:m

字符类

或: []

// 匹配 a 或 b 或 c
var string = 'a1b2c3d4'
var newString = string.replace(/[abc]/g,'X') //"X1X2X3d4"

字符类取反:[]^配合使用

//匹配a 或b 或 c之外的字符
var string = 'a1b2c3d4'
var newString = string.replace(/[^abc]/g,'X') //"aXbXcXXX"

范围类

[]-配合使用

var string = 'a1b2c3d4'
var newString = string.replace(/[a-z]/g,'Q') //"Q1Q2Q3Q4"
var string1 = 'a1b2c3d4A1B2C3D4'
var newString1 = string1.replace(/[a-z]/g,'Q') //"Q1Q2Q3Q4A1B2C3D4"
var newString2 = string1.replace(/[a-zA-Z]/g,'Q') //"Q1Q2Q3Q4Q1Q2Q3Q4"

单独匹配 -

var string = '2019-08-17'
//匹配0 1 2 和 -
var newString = string.replace(/[0-2-]/g,'A') //"AAA9AA8AA7"

预定义类

  1. . :除了回车换行之外的所有字符
  2. \d: [0-9] 数字字符
  3. \D: [^0-9] 非数字字符
  4. \s: 空白符
  5. \S: 非空白符
  6. \w: [a-zA-Z_0-9] 单词字符
  7. \W: [^a-zA-Z_0-9] 非单词字符

边界

  1. ^ : 开头
//^单独使用表示开头,与[]配合使用表示取反
var string1 = '@123@344@'
string1.replace(/@./g,'M') //"M23M44@"
var string2 = '@123@344@'
string2.replace(/^@./g,'M') //"M23@344@"
  1. $ : 结尾
var string = '@123@1233@'
string.replace(/.@/g,'M') //"@12M123M"
var string1 = '@123@1233@'
string1.replace(/.@$/g,'M') //"@123@123M"
  1. \b: 单词边界
//字面量
var reg = /\bis\b/g
'He is a boy. This is a girl'.replace(reg, 'IS') //"He IS a boy. This IS a girl"
//构造函数
var reg = new RegExp('\\bis\\b','g')
'He is a boy. This is a girl'.replace(reg, 'IS') //"He IS a boy. This IS a girl"
  1. \B: 非单词边界
//单词边界和非单词边界的使用
var string = 'This is a boy'
string.replace(/\Bis\b/g, 'IS') //"ThIS is a boy"

量词

两次是作用于紧挨着他的字符串

  1. {n}: 出现n次
//匹配数字出现20次的场景
var reg = /\d{20}/g
  1. {n,m}: 出现n到m次
  2. {n,}: 至少出现n次
  3. + :至少出现一次
  4. * :任意次
  5. ?:最多出现一次

贪婪模式

会尽可能多的匹配

  • 默认是贪婪模式
var string = '12345678'
string.replace(/\d{3,6}/g,'X') //'X78'

非贪婪模式

让正则表达式尽可能少的匹配,也就是一旦成功匹配

  • 使用方法:在两次后面加一个?
var string = '12345678'
string.replace(/\d{3,6}?/g,'X') //'XX78'

分组

()可以达到分组的目的

匹配小写字母和数字连续出现三次的情况

//连续出现3次的是数字,没有小写字母
var reg = /[a-z]\d{3}/g  
'a1b2c3d4'.replace(reg,'M') /没有匹配到
//小写字母和数字连续出现三次
var reg = /([a-z]\d){3}/g  
'a1b2c3d4'.replace(reg,'M') /"Md4"

|与()配合使用

var reg = /on|ca/g
'onca'.replace(reg, 'X')  //XX
var reg = /M(on|ca)day/g
'MondayMcaday'.replace(reg,'X') //XX

反向引用

'2015-12-23'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$1/$2/$3') //"2015/12/23"
  • 面试中遇到的一道面试题:将手机号的中间四位用****代替
var reg = /(\d{3})(\d{4})(\d{4})/g
'18311112222'.replace(reg,'$1****$2') //183****1111

忽略分组

'2015-12-23'.replace(/(?:\d{4})-(\d{2})-(\d{2})/g, '$1/$2') //"12/23"

前瞻

  1. JS中不支持后顾
  2. 正向前瞻 exp(?=assert)
// 匹配单词字符,并且单词字符后面是数字的
var reg = /\w(?=\d)/g
'a2*3'.replace( reg , 'X')  //"X2*3"
  1. 负向前瞻 exp(?!assert)
// 匹配单词字符,并且单词字符后面不是数字的
var reg = /\w(?!\d)/g
'a2*3dd'.replace( reg , 'X')  //"aX*XXX"

JS中的RgeExp对象

exec():作用是捕获分组

  1. 匹配成功返回一个数组,匹配失败返回null
  2. index:表示匹配文本在字符串中的位置
  3. input:表示应用正则表达式的字符串
  4. 第一个元素:与整个模式匹配的字符串
  5. 其他元素:与模式中的分组匹配的字符串
var text = 'cat,bat,sat,fat'
var reg = /.at/
var matches = reg.exec(text)

var text = 'cat,bat,sat,fat'
var reg = /(.at)/
var matches = reg.exec(text)

test()

用test()方法的时候最好使用非全局调用

//每次都从头匹配
var reg = /\w/
//匹配完整个字符串在从头匹配
var reg1 = /\w/g    
while(reg.test('ab')){
    console.log(reg1.lastIndex) // 死循环一直输出0
}
while(reg1.test('ab')){
    console.log(reg1.lastIndex) // 1 2
}