之前写正则都是各种上网搜索,还是没有系统的学习过正则表达式的用法,今天稍稍研究了一下下,感觉还是收获颇丰的,分享给各位,希望对于你们有所帮助~~
修饰符
-
g --全局匹配
-
i --不区分大小写,默认区分
-
m --多行搜索
预定义类字符
-
d : 数字;[0-9]
-
D : 非数字字符;[^0-9]
-
s : 空白符;[tnx0Bfr]
-
S : 非空白符;[^tnx0Bfr]
-
w : 单词字符(字母,数字,下划线);[a-zA-Z_0-9]
-
W : 非单词字符;[^a-zA-Z_0-9]
字符类
-
[] : 表示字符类 [] 中的^ 表示取反,- 表示范围如:[0-9][a-z] ;
量词
-
? : 出现0次或者1次(最多出现一次);
-
+ : 出现1次或者多次(最少出现1次);
-
* : 出现0次或者多次(任意次);
-
{n} : 出现n次;
-
{n,m} : 出现n到m次
-
{n,} : 至少出现n次;
常用的边界字符
-
^ : 以xxxx开始;
-
$ : 以xxxx结尾;
-
b : 单词边界;
-
B : 非单词边界;
贪婪模式
如d{3,6} 匹配3-6个数字,那么 "12345678"就会匹配d{6}
非贪婪模式
在量词后面加上?就会尽可能少的匹配了,上面的例子d{3,6}? 就会匹配d{3} 了
分组
想要匹配abc重复三次的场景,abc{3} 不就行了?事实上abc{3} 匹配的是c{3},若想匹配abc3次则需要用到分组的概念了; 正则中()表示分组,及(abc){3} 为匹配 abc 3次 $n代表匹配的分组 如:2018-03-03匹配换成2018年03月03日?
"2018-03-01".replace(/(d{4})-(d{2})-(d{2})/g,"$1年$2月$3日");
分组中不想被匹配到的分组在分组中加上?: 就可以了,如上例:
"2018-03-01".replace(/(d{4})-(?:d{2})-(d{2})/g,"$1年$2月$3日");
这时第二个分组就不会被捕获,就相当于有两个分组,所以不存在$3 这时的输出结果就会是 "2018年01月$3日";
或
aaa | bbb 两个同时匹配
前瞻,后顾
前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言("前"的概念就是正则表达式从文本头部向尾部开始解析) Javascript 不支持后顾所以这里就不做过多研究了哈。 -符合特定断言为 肯定/正向 匹配 正向前瞻:exp(?=assert) 例子:
"s3&df34a7".replace(/w(?=d)/g,'OK');
会输出 "OK3&dOKOK4OK7" 即找到匹配的单词(w)后会再次匹配后面的字符是不是数字,如果是则当前匹配的字符替换为OK,本次替换的单词(w)是s,f,3,a
-不符合特定断言为 否定/负向 匹配 负向前瞻:exp(?!assert) 栗子:
"s3&df34a7".replace(/w(?=d)/g,'OK');
会输出 "sOK&OKf3OKaOK" 即找到匹配的单词(w)后会再次匹配后面的字符是不是数字,如果不是则当前匹配的字符替换为OK,本次替换的单词(w)是3,d,4,7。把7算进来我认为是匹配到7的时候后面没有字符了是空也不是数字所以被替换了,如果不对还请大神指正哈。
对象属性
-
global 是否全文搜索,默认为false ,修饰符中的g;
-
ignoreCase 是否大小写敏感,默认为false ,修饰符中的i;
-
multiline 多行搜索,默认为false ,修饰符中的m;
-
lastIndex 是当前表达式匹配内容的最后一个字符的下一个位置(有点绕哈,后面会解释);
-
source 正则表达式的文本字符串;
举个栗子:
var reg = /w/gim;
reg.global // true
reg.ignoreCase //true
reg.source // "w"
方法
方法一
-
RegExp.prototype.test(str) 用于测试字符串参数中是否存在匹配正则表达式模式的字符串,如果存在则返回true ,否则返回false ;
举个栗子:
var reg1 = /w/;
reg1.test('a'); // true
reg1.test('#'); // false
reg1.test('a'); // true
reg1.test('#'); // false
再举个栗子:
var reg2 = /w/g;
reg2.test('a'); // true
reg2.test('#'); // false
reg2.test('a'); // false
reg2.test('a'); // true
reg2.test('a'); // false
看到区别了么?当全局检索时为什么第二次执行reg2.test('a'); 时返回false 呢?现在就要说说上文提到的对象属性lastIndex 啦,没记住的回到上面看看定义,当第一次执行时我们获取到的lastIndex 是1,那下一次就会从2的位置开始执行,而我们可以知道2的位置是没有字符的,所以返回false ,第三次执行的时候有返回了true 是因为查询到没有字符了lastIndex 又重置了。同样的你也可以测试reg2.test('aaa') 第四次执行的时候就会是false了,需要知道的是,只有在全局检索时(g)lastIndex 才会生效,否则的话只会返回 0 哦
方法二
非全局调用
调用非全局的RegExp 对象的exec() 方法时,返回数组
- 第一个元素是与正则表达式相匹配的文本
- 第二个元素是与
RegExp 对象的第一个子表达式(上文中的分组)相匹配的文本(如果有的话)
- 第二个元素是与
RegExp 对象的第二个子表达式(上文中的分组)相匹配的文本(如果有的话),以此类推
举个栗子:
var reg = /d(w)(w)d/;
var text = '1az2bc3cf4df5gf';
var regexec = reg.exec(text);
console.log(reg.lastIndex + 't' + regexec.index + 't' + regexec.toString()); //0 0 1az2,a,z
因为是非全局调用所以reg.lastIndex 返回 0;regexec.index 返回了0,匹配到的文本的第一个字符是"1",index也就是0,regexec 返回的数组第一元素是与reg 相匹配的文本,第二个元素是该文本中的符合正则表达式中第一个分组(w)的文本是"a" 后面的z同理。
全局调用
再来看看全局调用的例子
var reg = /d(w)(w)d/g;
var text = '1az2bc3cf4df5gf';
while(regexec = reg.exec(text)){
console.log(reg.lastIndex + 't' + regexec.index + 't' + regexec.toString());
}
// 4 0 1az2,z
// 10 6 3cf4,c,f
全局调用 lastIndex 生效 分别读取到1az2 和3cf4 的下一个字符的位置,后面与非全局调用同理,不过全局调用返回的是整段字符串符合规则的文本。
嗯哼,这篇文章就到这里了,如果对你有所帮助点个赞啦猫大在此谢过啦 本文会在个人博客更新的哦,博主可好了,有空溜达溜达~~~ (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|