目录
正则表达式学习笔记
正则表达式使用单个字符串用来描述、匹配一系列符合某个句法规则的字符串。
在Javascript中的正则表达式,可以帮助我们迅速的完成字符串的判断或者处理。
RegExp对象
Javascript通过内置对象RegExp支持正则表达式。
字面量
语法:/pattern/attributes
直接使用正则表达式字符串。
// 替换字符串中的is单词
var reg = /\bis\b/;
// 仅替换了第一个is:"He IS a boy. This is a dog. Where is she?"
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS');
// g替换字符串中所有的is
var reg = /\bis\b/g;
// 字符串中所有的is都被替换掉了:"He IS a boy. This IS a dog. Where IS she?"
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS');
构造函数
语法:new RegExp(pattern, attributes);
参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。
参数 attributes 是一个可选的字符串,包含属性 “g”、“i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配。ECMAScript 标准化之前,不支持 m 属性。如果 pattern 是正则表达式,而不是字符串,则必须省略该参数。
使用RegExp的构造函数,返回一个新的 RegExp 对象,具有指定的模式和标志。
// 替换字符串中的is单词
var reg = new RegExp('\\bis\\b)';
// 仅替换了第一个is:"He IS a boy. This is a dog. Where is she?"
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS');
// g替换字符串中所有的is
var reg = new RegExp('\\bis\\b', 'g');
// 字符串中所有的is都被替换掉了:"He IS a boy. This IS a dog. Where IS she?"
'He is a boy. This is a dog. Where is she?'.replace(reg, 'IS');
元字符
一般的字符串,例如abc属于原义文本字符,表示匹配的就是字符串本身。
而元字符是在正则表达式中有特殊含义的非字母字符:*+?$^.|\(){}[]
字符类
一般情况下正则表达式一个字符对应字符串一个字符。而在实际使用过程中,我们更多的是给出一个规则,来匹配多种符合规则的结果。
我们可以使用元字符[]来构建一个简单的类。所谓类是指符合某些特性的对象,一个繁殖,而不是特指某个字符。
// `[abc]`表示one of 'a' 'b' 'c',找出a或b或c:X1X2X3d4
'a1b2c3d4'.replace(/[abc]/g, 'X');
字符类取反
使用元字符^创建反向类/负向类。反向类的意思是不属于某类的内容。
// 表达式[^abc]表示不是字符a或b或c的内容:aXbXcXXX
'a1b2c3d4'.replace(/[^abc]/g, 'X');
范围类
通过给类增加一个符号-,来表示在一个闭区间中的类。
// [a-z]表示从a-z的任意字符:Q1Q2Q3Q4Q9
'a1b2d3x4z9'.replace(/[a-z]/g, 'Q');
在[]组成的类内部是可以连写的。
// [a-zA-Z]表示从a-z的任意字符:Q1Q2Q3Q4Q9QQQQ
'a1b2d3x4z9ABCD'.replace(/[a-zA-Z]/g, 'Q');
预定义类
| 字符 | 含义 |
|---|---|
| . | 除了回车符和换行符之外的所有字符 |
| \d | 数字字符 |
| \D | 非数字字符 |
| \s | 空白符 |
| \S | 非空白符 |
| \w | 单词字符(字母、数字、下划线) |
| \W | 非单词字符 |
| ^ | 以 xxx开始 |
| $ | 以xxx结束 |
| \b | 单词边界 |
| \B | 非单词边界 |
注:大写表示取反。
边界
| 字符 | 含义 |
|---|---|
| ^ | 以 xxx开始 |
| $ | 以xxx结束 |
| \b | 单词边界 |
| \B | 非单词边界 |
注:大写表示取反。
这里的边界指的是字符串的边界,当使用一个多行字符串的时候,需要结合’m’标志来进行多行匹配。
// 在多行字符串中\n往往会被边界字符串忽略
var str = "@123\n@456\n@789"
// 只匹配到了第一行开始的@,因为\n被忽略了:
// "X23
// @456
// @789"
str.replace(/^@\d/g, 'X');
// 使用m标志后,被忽略的\n就会突出它的存在感
var str = "@123\n@456\n@789"
// 匹配到了所有行开始的@:
// "X23
// X56
// X89"
str.replace(/^@\d/gm, 'X');
量词
即表示数量的词,通过以下符号来表示:
| 字符 | 含义 |
|---|---|
| ? | 出现0次或1次(最多出现1次) |
| + | 出现1次或多次(至少出现1次) |
| * | 出现0次或多次(任意次) |
| {n} | 出现n次 |
| {n,m} | 出现n到m次 |
| {n,} | 至少出现n次 |
贪婪模式与非贪婪模式
贪婪模式
正则表达式在匹配过程中,会尽可能多的匹配,直到匹配失败。
// 根据贪婪模式原则,优先匹配6个数字:"X78"
'12345678'.replace(/\d{3,6}/g, 'X')
非贪婪模式
让这种表达式尽可能少的匹配,也就是说一旦成功匹配不再继续尝试就是非贪婪模式。
做法很简单,在量词后加上?即可。
// 根据非贪婪模式原则,匹配到3之后就满足条件了,顾结束匹配:"XX78"
'12345678'.replace(/\d{3,6}?/g, 'X')
分组
为了匹配某个特定单词,或圈定的内容,可以使用()来分组。
// 匹配字母加数字的组合出现3次的字符串:"Xd4"
'a1b2c3d4'.replace(/([a-z]\d){3}/g,'X')
或
通过符号|表示,和代码中常用的或的意思是一样的。
// 表示c或者e都可以,使用abcfg和abefg都符合要求:"XX"
'abcfgabefg'.replace(/ab(c|e)fg/g, 'X')
反向引用
分组中的内容可以使用$进行捕获,将捕获到的内容可以作为变量重新组合成新的字符串进行替换。
// "11/25/2016"
'2016-11-25'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$2/$3/$1')
忽略分组
如果不希望捕获某些分组,只需要在分组内加上?:就可以了。
// 忽略分组后,$1指向ok,所以结果为:"ok"
'ByronCCok'.replace(/(?:Byron).+(ok)/g, '$1')
前瞻
正则表达式从文本头部向尾部开始解析,文本尾部方向,成为“前”。
前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言。后顾/后瞻方向相反。(Javascript不支持后顾)
符合不符合特定断言成为肯定/正向匹配和否定/负向匹配。
| 名称 | 正则 |
|---|---|
| 正向前瞻 | exp(?=assert) |
| 负向前瞻 | exp(?!assert) |
// \w是正则规则,(?=\d)是正则断言,只有规则才参与正则表达式的匹配结果,断言只是辅助的二次验证
// 这里a符合\w的规则,同时也符合后面跟着\d的断言,所以匹配结果为:"X2*3"
'a2*3'.replace(/\w(?=\d)/g, 'X')
// 这里2和3符合\w的规则,同时也符合后面跟着的不是\d的断言,所以匹配结果为:"aX*X"
'a2*3'.replace(/\w(?!\d)/g, 'X')
Javascript对象属性
对象属性如下:
| 属性 | 含义 | 默认值 |
|---|---|---|
| global | 全文搜索 | false |
| ignore case | 大小写敏感 | false |
| multiline | 多行搜索 | false |
| lastIndex | 当前表达式匹配内容的最后一个字符的下一个位置 | |
| source | 正则表达式的文本字符串 |
var reg1 = /\w/;
var reg2 = /\w/gim;
reg1.global; // false
reg2.global; // true
reg1.lastIndex; // 0 非全局下lastIndex不生效
reg1.source; // "\w"
注:这里的对象属性是只读的,不可进行修改。
正则表达式的方法
test(str)
用于测试字符串参数中是否存在匹配正则表达式模式的字符串。
如果存在则返回true,否则返回false。
var reg1 = /\w/;
reg1.test('a'); // true
test(str)方法是作用于正则对象本身的,找到符合条件的字符串,便返回结果。因此会导致正则对象的lastIndex属性的值的变化。
var reg2 = /\w/g;
// 由于对象lastIndex的数值变化,导致第三次测试结果为false
reg2.test('ab'); // true
reg2.test('ab'); // true
reg2.test('ab'); // false
// 三次执行的lastIndex结果如下:
// 1
// 2
while(reg2.test('ab')){
console.log(reg2.lastIndex);
}
exec(str)
使用正则表达式模式对字符串执行搜索,并将更新全局RegExp对象的属性以反映匹配结果。
如果没有匹配的文本则返回null,否则返回一个结果数组:
index声明匹配文本的第一个字符的位置input存放被检索的字符串string
非全局调用
调用非全局的RegExp对象的exec()时,返回数组的第一个元素是正则表达式相匹配的文本,第二个元素是与RegExpObject的第一个分组相匹配的文本(如果有的话),第三个元素是与RegExp对象的第二个分组相匹配的文本(如果有的话),以此类推。
var ts = '1a2b3c4d5e';
var reg3 = /\d(\w)\d/;
var ret = reg3.exec(ts);
// 非全局情况下lastIndex无效
// 第一个元素的位置是0,第一个元素是“1a2“,第二个元素根据分组(\w)匹配到“a”
console.log(reg3.lastIndex + '\t' + ret.index + '\t' + ret.toString()); // "0 0 1a2,a"
console.log(reg3.lastIndex + '\t' + ret.index + '\t' + ret.toString()); // "0 0 1a2,a"
全局调用
调用非全局的RegExp对象的exec()时,返回数组同非全局调用。只是lastIndex具有了实际意义,且在循环遍历的过程中,可以将符合匹配规则的字符串全部取出。
var ts = '1a2b3c4d5e';
var reg4 = /\d(\w)\d/g;
// "3 0 1a2,a"
// "7 4 3c4,c"
while(ret = reg4.exec(ts)){
console.log(reg4.lastIndex + '\t' + ret.index + '\t' + ret.toString());
}
与正则表达式相关的字符串对象方法
search(reg)
用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。
方法返回第一个匹配结果index,查找不到返回-1。search()方法不执行全局匹配,它将忽略标志g,并且总是从字符串的开始进行检索。
var str = 'a1b2c3d1';
console.log(str.search('1')); // 1
console.log(str.search(/1/)); // 1
console.log(str.search(/1/g)); // g被忽略了:1
match(reg)
将检索字符串,以找到一个或多个与regexp匹配的文本。
regexp是否具有标志g对结果影响很大。
非全局调用
同exec()。
var reg3 = /\d(\w)\d/;
var ts = '$1a2b3c4d5e';
// ["1a2", "a"]
// "1 0"
var ret = ts.match(reg3);
console.log(ret);
console.log(ret.index + '\t' + reg3.lastIndex); // lastIndex无效
全局调用
表示regexp具有标志g,找到字符串中的所有匹配子字符串:
-
没有找到任何匹配的子字符串,则返回
null -
如果找到了一个或多个匹配子字符串,则返回一个数组
数组元素中存放的是字符串中所有的匹配子字符串,而且也没有index属性或者input属性。
var reg4 = /\d(\w)\d/g;
var ts = '$1a2b3c4d5e';
// ["1a2", "3c4"]
// "undefined 0"
var ret = ts.match(reg4);
console.log(ret);
console.log(ret.index + '\t' + reg4.lastIndex); // index和lastIndex都无效了
split(reg)
split()也是可以通过正则表达式进行处理的。
'a1b2c3d4e'.split(/\d/g); // ["a", "b", "c", "d", "e"]
replace(…)
replace(str, replaceStr)
'a1b2c3d4e'.replace('a1', 'X'); // "Xb2c3d4e"
replace(reg, replaceStr)
'a1b2c3d4e'.replace(/\d/g, 'X'); // "aXbXcXdXe"
replace(reg, function)
function会在每次匹配替换的时候调用,有四个参数:
- 匹配字符串;
- 正则表达式分组内容,没有分组则没有该参数;
- 匹配项在字符串中的
index; - 原字符串
var ts = '$1a2b3c4d5e';
/*
"1a2"
1
"3c4"
5
*/
ts.replace(/\d\w\d/g, function(match, index, orgin){
console.log(match);
console.log(index);
return 0;
});
/*
"1a2"
"12"
"3c4"
"34"
*/
ts.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, orgin){
console.log(match);
console.log(group1 + group3);
return 0;
});
来源:CSDN
作者:就只是小茗
链接:https://blog.csdn.net/sayUonly/article/details/103425504