- 不管如何使用正则表达式,都需要先匹配。匹配之后,才会有:验证、切分、提取、替换
验证
-
先说匹配:就是看目标字符串里是否有满足匹配的子串。匹配的本质就是查找
-
有没有匹配,是不是匹配上,判断是否的操作,即称为验证
-
使用 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)
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
属性始终不变 - 正则的两个方法
exec
和test
,当正则全局匹配时,每一次匹配完成后,都会修改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 相关注意
-
他的第二个参数表示数组的最大长度
let string = 'html,css,js' console.log(string.split(/,/, 2)) //[ 'html', 'css' ]
-
使用分组捕获:他的结果数组包含分隔符
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
的第二个参数既可以是字符串也可以是函数
属性 | 描述 |
---|---|
$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
- 参数:
- regexp|substr:正则表达式或者匹配的字符
- newSubstr|function:要替换的字符或者函数
function 参数 | 解释 |
---|---|
match | 匹配的子串 |
p1, p2, ... | 括号中的捕获组找到的第 n 个字符串 |
offset | 被检查的整个字符串中匹配子字符串的lastIndex |
string | 正在检查的整个字符串 |
- 不同:
- replace 只会匹配第一个匹配到的字符,
replaceAll
会匹配所有字符 - 如果是正则,
replaceAll
必须加上全局修饰符g
- replace 只会匹配第一个匹配到的字符,
'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
-
给捕获组分组
// 这里的语法是 ?<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' } //]
-
使用最新的 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] } // ] // ]