练习辅助
jsbin
图文并茂
什么是正则表达式
使用单个字符串来描述、匹配一系列符合某个句法规则的字符串
说简单了是按照某种规则去匹配符合条件的字符串
RegExp对象
通过内置对象RegExp支持正则表达式
有两种方法实例化RegExp对象
字面量
var reg = / \bis\b /g;
var reg = /\bis\b/
// undefined
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS')
// "He IS a boy. This is a dog. Where is she?"
var reg = /\bis\b/g
// undefined
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS')
// "He IS a boy. This IS a dog. Where IS she?"
构造函数
var reg = new RegExp('\bis\b', 'g')
var reg = new RegExp('\bis\b')
// undefined
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS')
// "He IS a boy. This is a dog. Where is she?"
var reg = new RegExp('\\bis\\b', 'g')
// undefined
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS')
// "He IS a boy. This IS a dog. Where IS she?"
修饰符
g:global 全文搜索,不添加,搜索到第一个匹配停止
i:ignore case 忽略大小写,默认大小写敏感:ignore case 忽略大小写,默认大小写敏感
m: lines 多行搜索
'He is a boy. Is he?'.replace(/\bis\b/g, '0')
// "He 0 a boy. Is he?"
'He is a boy. Is he?'.replace(/\bis\b/gi, '0')
// "He 0 a boy. 0 he?"
元字符
正则表达式由两种基本字符类型组成:
元字符是在正则表达式中有特殊含义字母字符
* + ? $ ^ . | \ () {} []
字符类
我们可以使用元字符 [ ] 来构建一个简单的类
所谓类是指符合某些特性的对象,一个泛指,而不是特指某个字符
表达式 [abc] 把字符 a 或 b 或 c 归为一类 ,表达式可以匹配这类的字符
字符类取反
使用元字符 ^ 创建 反向类/负向类
反向类的意思是不属于某类的内容
表达式 1表示 不是字符a或b或c的内容
'a1b2c3d4'.replace(/[abc]/g, 'X')
"X1X2X3d4"
'a1b2c3d4'.replace(/[^abc]/g, 'X')
"aXbXcXXX"
范围类
正则表达式还提供了范围类
我们可以使用 [a-z] 来连接两个字符表示从a到z的任意字符
这是个闭区间,也就是包含a和z本身
在 [] 组成的类内部是可以连写的 [a-zA-Z]
'a1b2c3x4z9'.replace(/[a-z]/g, 'Q')
// "Q1Q2Q3Q4Q9"
'a1b2c3x4z9SGASDGA'.replace(/[a-zA-Z]/g, 'Q')
// "Q1Q2Q3Q4Q9QQQQQQQ"
'2016-09-12'.replace(/[0-9]/g, 'A')
// "AAAA-AA-AA"
'2016-09-12'.replace(/[0-9-]/g, 'A')
// "AAAAAAAAAA"
JS预定义类及边界预定义类
正则表达式提供 预定义类 来匹配常见的字符集
匹配一个 ab + 数字 + 任意字符 的字符串,ab\d.
边界
正则表达式还提供了几个常用的边界匹配字符
'This is a boy'.replace(/is/g, '0')
// "Th0 0 a boy"
'This is a boy'.replace(/\bis\b/g, '0')
// "This 0 a boy"
'This is a boy'.replace(/\Bis\b/g, '0')
// "Th0 is a boy"
'@123@abc@'.replace(/@./g, 'Q')
// "Q23Qbc@"
'@123@abc@'.replace(/^@./g, 'Q')
// "Q23@abc@"
'@123@abc@'.replace(/.@/g, 'Q')
// "@12QabQ"
'@123@abc@'.replace(/.@$/g, 'Q')
// "@123@abQ"
mulSrt = "@123\n@456\n@789"
"@123
@456
@789"
mulSrt.replace(/^@\d/g, 'X')
"X23
@456
@789"
mulSrt.replace(/^@\d/gm, 'X')
"X23
X56
X89"
量词
\d{20}\w\d?\w+\d*\d{3}\w{3,5}\d{3,}
JS正则贪婪模式与非贪婪模式贪婪模式
尽可能多的匹配
非贪婪模式
让正则表达式尽可能少的匹配,也是说一旦成功匹配不再继续尝试就是非贪婪模式
做法很简单,在量词后加上?即可
'12345678'.replace(/\d{3,6}/g, 'X')
// "X78"
'12345678'.replace(/\d{3,6}?/g, 'X')
// "XX78"
'123456789' .match(/\d{3,5}?/g)
// (3) ["123", "456", "789"]
分组分组
使用 () 可以达到分组的功能js 怎么使用正则表达式,使量词作用域分组
(Byron){3}
'a1b2c3d4'.replace(/([a-z]\d){3}/g, 'X')
// "Xd4"
或
使用 | 可以达到或的效果
Byron | Casper!
Byr(on|Ca)sper
'ByronsperByrCasper'.replace(/Byr(on|Ca)sper/g, 'X')
// "XX"
反向引用
'2016-11-25'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '2/3/
// "11/25/2016"
忽略分组
不希望捕获某些分组,只需要在分组内加上 ?: 就可以
(?:Byron).(ok)
前瞻
正则表达式从文本头部向尾部开始解析,文本尾部方向,称为“前”
前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言,后顾/后瞻方向相反
不支持后顾
符合和不符合特定断言称为 肯定/正向 匹配和 否定/负向 匹配
\w(?=\d)
'a2*3'.replace(/\w(?=\d)/g, 'X')
// "X2*3"
'a2*34vv'.replace(/\w(?!\d)/g, 'X')
// "aX*3XXX"
JS对象属性
global:是否全文搜索js 怎么使用正则表达式,默认false
ignore case:是否大小写敏感,默认是 false
:多行搜索,默认值是 false
: 是当前表达式匹配内容的最后一个字符的下一个位置
source:正则表达式的文本字符串
var reg1 = /\w/
var reg2 = /\w/gim
console.log(re1.global) // false
console.log(re1.ignoreCase) // false
console.log(re1.multiline) // false
console.log(reg2.global) // true
console.log(reg2.ignoreCase) // true
console.log(reg2.multiline) // true
注意,属性是只读的
test 和 exec方法RegExp..test(str)
用于测试字符串参数中是否存在匹配正则表达式的字符串
如果存在则返回 true,否则返回 false
var reg1 = /\w/
reg1.test('a') // true
reg1.test('a') // true
reg1.test('a') // true
var reg2 = /\w/g
reg2.test('ab') // true
reg2.test('ab') // true
reg2.test('ab') // false 注意这里是 false
reg2.test('ab') // true
使用 test() 会作用于正则对象的 属性,知道匹配不到, 会变成 0
当前匹配结果的下一个字符
var reg1 = /\w/
var reg2 = /\w/g
while(reg2.test('ab')) {
console.log(reg2.lastIndex) // 依次是 1 2
}
RegExp..exec(str)
使用正则表达式模式对字符串执行搜索,井将更新全局RegExp对象的属性以反映匹配结果
如果没有匹配的文本则返回 null,否则返回一个结果数组:
index 声明匹配文本的第一个字符的位置
input 存放被检索的字符串 string
非全局调用
调用非全局的 RegExp 对象的 exec()时,返回数组
第一个元素是与正则表相匹配的文本
第二个元素是与 的第一个子表达式相匹配的文本(如果有的话)
第三个元素是与 RegExp 对象的第二个子表达式相匹配的文本(如果有的话),以些类推
var reg3 = /\d(\w)(\w)\d/
var ts = '$1az2bb3cy4dd5ee'
var ret = reg3.exec(ts)
console.log(reg3.lastIndex) // 0,非全局情况下,lastIndex 不生效,所以是 0
console.log(ret.index) // 1 // 匹配文本的第一个字符的位置
console.log(ret.toString()) // "1az2,a,z"
var reg4 = /\d(\w)(\w)\d/g
var ts = '$1az2bb3cy4dd5ee'
var ret
while(ret = reg4.exec(ts)) {
console.log(reg4.lastIndex + '\t' + ret.index + '\t' + ret.toString())
}
/*
console
"5 1 1az2,a,z"
"11 7 3cy4,c,y"
*/
字符串对象方法String..search(reg)
search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串
方法返回第一个匹配结果index,查找不到返回 -1
search() 方法不执行全局匹配,它将忽略标志 g,井且总是从字符串的开始进行检索
'a1b2c3d1'.search('1') // 1
'a1b2c3d1'.search('10') // -1
'a1b2c3d1'.search(1) // 1 ,数字会被转成正则 /1/
'a1b2c3d1'.search(/1/) // 1
String..match(reg)
match()方法将检索字符串,以找到一个或多个与regexp匹配的文本
regexp是否具有标志 g 对结果影响很大
非全局调用
var reg3 = /\d(\w)\d/
var ts = '$'
var ret = ts.match(reg3)
.log(ret) // ["1a2", "a"]
.log(ret.index) // 1
.log(reg3.) // 0 无效
全局调用
var reg4 = /\d(\w)\d/g
var ts = '$1a2b3c4d5e'
var ret = ts.match(reg4)
console.log(ret) // ["1a2", "3c4"]
console.log(ret.index) // undefined 没有
console.log(reg3.lastIndex) // 0 没有
String..split()
我们经常使用split方法把字符串分割为字符数组
'a,b,c,d'.split('.') // ['a','b','c','d']
在一些复杂的分割情况下我们可以使用正则表达式解决
''.split(/\d/) // ['a','b','c','d']
'a,b,c,d'.split(',') // ["a", "b", "c", "d"]
'a1b2c3d4e'.split(/\d/g) // ["a", "b", "c", "d", "e"]
'a,b,c,d'.split(/,/) // ["a", "b", "c", "d"]
String..参数含义
会在每次匹配替换的时候调用,有四个参数
1、匹配字符串
2、正则表达式分组内容,没有分组则没有该参数
3、匹配顶在字符串中的 index
4、原字符串
'a1b'.replace('1',2) // "a2b"
'a1b1c1'.replace('1',2) //"a2b1c1"
'a1b1c1'.replace(/1/g,2) //"a2b2c2"
'a1b1c1'.replace(/1/,2) //"a2b1c1"
'a1b2c3d4e5'.replace(/\d/g, function(match, index, origin){
return parseInt(match) + 1
}) // "a2b3c4d5e6"
'a1b2c3d4e5'.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, origin){
return group1 + group3
}) // "a12c34e5"
本文共 1287 个字数,平均阅读时长 ≈ 4分钟