Skip to content

Latest commit

 

History

History
368 lines (287 loc) · 9.47 KB

07正则表达式编程.md

File metadata and controls

368 lines (287 loc) · 9.47 KB

正则表达式编程

正则表达式的四种操作

  • 不管如何使用正则表达式,都需要先匹配。匹配之后,才会有:验证、切分、提取、替换

验证

  • 先说匹配:就是看目标字符串里是否有满足匹配的子串。匹配的本质就是查找

  • 有没有匹配,是不是匹配上,判断是否的操作,即称为验证

  • 使用 search

let string = 'abcd123'
let reg = /\d/
console.log(!!string.search(reg)) //true
  • 使用 test
let string = 'abcd123'
let reg = /\d/
console.log(reg.test(string)) //true
  • 使用 match
let string = 'abcd123'
let reg = /\d/
console.log(!!string.match(reg))
  • 使用 exec
let string = 'abcd123'
let reg = /\d/
console.log(!!reg.test(string))

切分

  • 切分就是把目标字符串切成一段一段的。在 js 中使用的是 split
let string = 'html,css,js'
console.log(string.split(/,/))
//[ 'html', 'css', 'js' ]

提取

  • 正则通常使用分组引用(分组捕获)功能,还需要配合使用相关的 API

  • 使用 match

let reg = /^(\d{4})\D(\d{2})\D(\d{2})$/
let string = '2019-01-01'
console.log(string.match(reg))
//[ '2019-01-01','2019','01','01',index: 0,input: '2019-01-01',groups: undefined ]
  • 使用 exec
let reg = /^(\d{4})\D(\d{2})\D(\d{2})$/
let string = '2019-01-01'
console.log(reg.exec(string))
//[ '2019-01-01','2019','01','01',index: 0,input: '2019-01-01',groups: undefined ]
  • 使用 test 或者 search
let reg = /^(\d{4})\D(\d{2})\D(\d{2})$/
let string = '2019-01-01'
reg.test(string)
//string.search(reg)
console.log(RegExp.$1, RegExp.$2, RegExp.$3)
  • 使用 replace
let reg = /^(\d{4})\D(\d{2})\D(\d{2})$/
let string = '2019-01-01'
let date = []
string.replace(reg, function (match, year, month, day) {
  date.push(year, month, day)
})
console.log(date)

替换

  • yyyy-mm-dd 转化成 yyyy/mm/dd
let string = '2019-01-01'
let today = string.replace(/-/g, '/')
console.log(today)

正则相关 API

String#search
String#split
String#match
String#replace
RegExp#test
RegExp#exec
  • 字符串示例的 4 个方法都支持正则和字符串
  • 但是 search 和 match 都会将字符串转化为正则
    • 最好一开始就写成正则
let string = '2019.01.01'
console.log(string.search('.')) //0
//需要写成 /\./ 的形式

match 返回结果的格式问题,与正则对象是否有修饰符 g 有关

let string = '2019.01.01'
let reg1 = /\b(\d+)\b/
let reg2 = /\b(\d+)\b/g
console.log(string.match(reg1))
//[ '2019','2019',index: 0,input: '2019.01.01',groups: undefined ]
console.log(string.match(reg2))
//[ '2019', '01', '01' ]
  • 没有 g 返回的是标准格式,即数组的第一个元素是整体匹配的内容,接下来是分组捕获的内容,然后是整体匹配的下标,随后是输入的内容
  • g 返回的是所有匹配的内容

matchAll:方法返回对字符串使用正则表达式的所有匹配项(返回一个迭代器)

  • 必须添加全局修饰符 g
let string = '2019.01.01'
let reg1 = /\b(\d+)\b/g
for (let str of string.matchAll(reg1)) {
  console.log(str)
}
//[ '2019','2019',index: 0,input: '2019.01.01',groups: undefined ]
//[ '01', '01', index: 5, input: '2019.01.01', groups: undefined ]
//[ '01', '01', index: 8, input: '2019.01.01', groups: undefined ]

exec

let string = '2019.01.01'
let reg2 = /\b(\d+)\b/g
console.log(reg2.exec(string))
console.log(reg2.lastIndex)
console.log(reg2.exec(string))
console.log(reg2.lastIndex)
console.log(reg2.exec(string))
console.log(reg2.lastIndex)
console.log(reg2.exec(string))
console.log(reg2.lastIndex)

//[ '2019','2019',index: 0,input: '2019.01.01',groups: undefined ]
//4
//[ '01', '01', index: 5, input: '2019.01.01', groups: undefined ]
//7
//[ '01', '01', index: 8, input: '2019.01.01', groups: undefined ]
//10
//null
//0
  • 实例 lastIndex 属性表示下一次匹配开始的位置

修饰符 g 对 exec 和 test 的影响

  • lastIndex 属性表示尝试匹配时从字符串的 lastIndex 位开始匹配
  • 字符串的四个方法,每次匹配时,都是从 0 开始,即 lastIndex 属性始终不变
  • 正则的两个方法 exectest,当正则全局匹配时,每一次匹配完成后,都会修改 lastIndex
let regex = /a/g
console.log(regex.test('a'), regex.lastIndex)
console.log(regex.test('aba'), regex.lastIndex)
console.log(regex.test('ababc'), regex.lastIndex)
// => true 1
// => true 3
// => false 0

test 整体匹配时需要使用 ^$

  • test 是看目标字符串是否有子串匹配正则,即有部分匹配即可
  • 如果要整体匹配,正则前后需要添加开头和结尾
console.log(/123/.test('a123b'))
// => true
console.log(/^123$/.test('a123b'))
// => false
console.log(/^123$/.test('123'))
// => true

split 相关注意

  1. 他的第二个参数表示数组的最大长度

    let string = 'html,css,js'
    console.log(string.split(/,/, 2))
    //[ 'html', 'css' ]
  2. 使用分组捕获:他的结果数组包含分隔符

    let str = 'html,css,js'
    console.log(str.split(/(,)/))
    //[ 'html', ',', 'css', ',', 'js' ]

关于 flags 参数:

选项 参数
g 全局匹配.找到所有匹配,而不是在第一个匹配结束
i 忽略字母大小写
m 多行,将(^$)视为多行工作,不只是匹配整个输入字符串最开始和结束
s dotAll 模式,匹配任何字符串,例如 \n
u uniCode,将模式视为 Unicode 序列点的序列
y 粘性匹配。从上次匹配成功的下个位置开始后续匹配。若下个相符内容不紧接在后,则不继续匹配
let reg = /\w/gim
console.log(reg.global) //true
console.log(reg.ignoreCase) //true
console.log(reg.multiline) //true

source:构建动态正则的时候查看其属性

let className = 'high'
let regex = new RegExp('(^|\\s)' + className + '(\\s|$)')
console.log(regex.source) //(^|\s)high(\s|$)

replace

  • replace 的第二个参数既可以是字符串也可以是函数
属性 描述
$1,$2,…,$99 匹配第 1-99 个 分组里捕获的文本
$& 匹配到的子串文本
$ 匹配到的子串的左边文本
$' 匹配到的子串的右边文本
$$ 美元符号

使用分组捕获的文本

let result = '2,3,5'.replace(/(\d+),(\d+),(\d+)/, '$3=$1+$2')
console.log(result) //5=2+3

$& 获得所有子串文本

let result = '2,3,5'.replace(/(\d+)/g, '$&$&$&')
console.log(result) //222,333,555

$':匹配到子串的右侧文本,$`匹配到子串的右侧文本

let result = 'b235a'.replace(/(\d+)/, "$'")
console.log(result) //baa
let result = 'b235a'.replace(/(\d+)/, '$`')
console.log(result) //bba

replace 和 replaceAll

  • 参数:
    1. regexp|substr:正则表达式或者匹配的字符
    2. newSubstr|function:要替换的字符或者函数
function 参数 解释
match 匹配的子串
p1, p2, ... 括号中的捕获组找到的第 n 个字符串
offset 被检查的整个字符串中匹配子字符串的lastIndex
string 正在检查的整个字符串
  • 不同:
    1. replace 只会匹配第一个匹配到的字符,replaceAll会匹配所有字符
    2. 如果是正则,replaceAll 必须加上全局修饰符 g
'1234 2345 3456'.replace(
  /(\d)\d{2}(\d)/g,
  function (match, p1, p2, index, input) {
    console.log([match, p1, p2, index, input])
  }
)

//[ '1234', '1', '4', 0, '1234 2345 3456' ]
//[ '2345', '2', '5', 5, '1234 2345 3456' ]
//[ '3456', '3', '6', 10, '1234 2345 3456' ]

匹配索引

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

  1. 给捕获组分组

    // 这里的语法是 ?<group>
    const regex = /(?<sy>.un)/dg
    const str = 'sun and yun and nun'
    console.log(regex.exec(str))
    //[
    //  'sun',
    //  'sun',
    //  index: 0,
    //  input: 'sun and yun and nun',
    //  groups: [Object: null prototype] { sy: 'sun' }
    //]
  2. 使用最新的 flag 参数 /.../d,它会返回匹配到值的索引范围

    • 第一个值是二维数组,其中第一个数组表示正则匹配的范围,其余是捕获组中的索引范围
    • 第二个是分组(?<group>
    const str = 'sun and yun and nun'
    const regex = /(?<sy>.un)/dg
    console.log(regex.exec(str))
    // [
    //   'sun',
    //   'sun',
    //   index: 0,
    //     input: 'sun and yun and nun',
    //       groups: [Object: null prototype] { sy: 'sun' },
    // indices: [
    //   [0, 3],
    //   [0, 3],
    //   groups: [Object: null prototype] { sy: [Array] }
    // ]
    // ]