匹配模式
- i —— 忽略大小写
- g —— 全局匹配
- m —— 多行匹配(要匹配的字符串中间有换行,通常和 g 一起使用)
var str1 = 'ababab';
var str2 = 'ab\nabc';
var regexp1 = /ab/g;
var regexp2 = /ab/m;
var regexp3 = /^ab/g;
var regexp4 = /^ab/m;
var regexp5 = /^ab/mg;
var res1 = str1.match(regexp1);
var res2 = str1.match(regexp2);
var res3 = str2.match(regexp1);
var res4 = str2.match(regexp2);
var res5 = str2.match(regexp3);
var res6 = str2.match(regexp4);
var res7 = str2.match(regexp5);
console.log(res1);//[ 'ab', 'ab', 'ab' ]
console.log(res2);//[ 'ab', index: 0, input: 'ababab', groups: undefined ]
console.log(res3);//[ 'ab', 'ab' ]
console.log(res4);//[ 'ab', index: 0, input: 'ab\nabc', groups: undefined ]
console.log(res5);//[ 'ab' ]
console.log(res6);//[ 'ab', index: 0, input: 'ab\nabc', groups: undefined ]
console.log(res7);//[ 'ab', 'ab' ]
表达式
ps:
1.正则里面规则是从左到右的(按顺序)
2.字符串被匹配完以后就不会再被匹配了,不会!!!!!!!!!
- [] —— 表达式, 一个 " [] "(表达式) 代表一位, 里面的内容表示的是这一位可以取到的范围
- [^] —— !表达式,里面的内容表示的是这一位不可以取得值
- [a-z]
- [A-Z]
- [A-z] —— A(ASCI码:65)-Z + a(ASC码:97)-z
- [0-9]
- [\u4e00-\u9fa5] —— 中文
- () —— 子表达式(分组),代表一个表达式区间
() 和 [] 的区别?
var reg1 = /[abc|def|ghi]/g;
var reg2 = /(abc|def|ghi)/g;
var str = 'mnvcva';
reg1.test(str); //true
reg2.test(str); //false
元字符
其实也是表达式,是表达式的翻译版本
- \w —— === [0-9A-z_]
- \W —— === [^\w]
- \d —— === [0-9]
- \D —— ===[^\d]
- \s —— 空白字符,包括 \n , \r , \f , \t , \v
- \S —— [^\s]
- \b —— 单词边界
- \B —— 非单词边界
- . —— [^\r\n] 除了\r ,\n的任意字符
单词边界?
eg1.
var str = 'abc def ghi'; //有6个单词边界
eg2.
var reg = /\bcde/g;
var str = 'abc cde fgh';
str.match(reg); // ["cde"]
var reg2 = /\bcde\b/g;
str.match(reg2); // ["cde"]
var str2 = "abc cdefgh";
str2.match(reg2); // null
量词
注意:能匹配多不匹配少(正则是贪婪匹配原则),会尽可能多的匹配
- n+ —— {1, }
- n* —— {0, }
var reg = /\w*/g;
var str = 'abc';
str.match(reg); // ["abc", ""]
// 为什么还有个""?
// 因为 正则的匹配是全局的,当匹配完abc,光标所在的位置是c,c后面还有一个逻辑位,被匹配为了""
var reg = /\d*/g;
var str = 'abc';
str.match(reg); //["","","",""] 匹配的是4个逻辑位(好像不叫逻辑位~,叫什么忘记了)
- n? —— {0, 1}
- n{X} —— {x}
- n{x, y} —— {x, y}
- n{x,} —— {x, }
- ?=n —— 正向预查(也可叫正向断言)(后面有详细使用方法)
- ?!n —— 非正向预查(非正向断言)
反向引用
反向引用:var reg = /(\w)/ —— 其中"()" (括号)会记录里面所匹配的内容, 可以利用 “\1” 来引用出来!“\1” 表示的是引用第一个子表达式(分组)(即第一个括号)里面的内容,以此类推,“\2” 表示的是引用第二个子表达式(分组)里面的内容
举个栗子
var reg = /(\w)\1\1\1/g;
var str = 'aaaabbbb';
str.match(reg); // ["aaaa", "bbbb"]
正则表达式实例的方法和属性
注意:如果要返回的是匹配得到的结果,它都是根据正则的规则,匹配到的内容!而不包含其他!!!!
方法:
- regexp.test(string) 字符串是否符合正则的规则 —— true / false
- regexp.exec(string) ——
(1)返回一个类数组 [{"匹配的内容", index: xx, input: '匹配的字符串',groups:xx}]
(2)当正则里面有子表达式时:返回一个类数组[{"匹配的内容",“第一个子表达式匹配的内容”, "第二个子表达式匹配的内容", .... index: xx, input: .....同上}]
var reg = /ab/g;
var str = 'ababab';
console.log(reg.exec(str))
//["ab", index: 0, input: "ababab", groups: undefined]
console.log(reg.lastIndex)
//2
console.log(reg.exec(str))
//["ab", index: 2, input: "ababab", groups: undefined]
console.log(reg.lastIndex)
//4
console.log(reg.exec(str))
//["ab", index: 4, input: "ababab", groups: undefined]
console.log(reg.lastIndex)
//6
console.log(reg.exec(str))
//null
console.log(reg.lastIndex)
//0
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
var reg = /ab/;
var str = 'ababab';
console.log(reg.exec(str))
// ["ab", index: 0, input: "ababab", groups: undefined]
console.log(reg.lastIndex)
//0
console.log(reg.exec(str))
// ["ab", index: 0, input: "ababab", groups: undefined]
console.log(reg.lastIndex)
//0
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
所以,如果正则的匹配模式不是 global 的时候,游标的位置每次都是0
字符串中与正则相关的方法:
- string.match(regexp) —— 返回匹配了正则的字符串数组 (这个是字符串的方法)
(1)当不是全局匹配,返回的是一个类数组:["匹配到的内容", index: xx, input: '原始字符串', groups: ...]
(2)如果式全局匹配,返回的是一个数组:["匹配的第一个值", "匹配的第二个值", ...],数组里面的每一项都是根据正则所匹配到的内容
- string.search(regexp) —— 返回匹配的位置(与lastIndex没有关系),匹配不到返回 -1 。
var reg = /abc/g;
var reg2 = /abc/;
var str = 'fk abc def abc';
console.log(str.search(reg));//3
console.log(str.search(reg2));//3
// 无论是不是全局匹配,返回的结果都是一样的,所以它与lastIndex的值无关系
- string.split(regexp) —— 按照正则拆分字符串
- string.replace(regexp ,func / string}) —— 替换内容(第一个参数也可以是字符串),第二个参数可以是一个匹配正则后的回调函数(每次匹配都会执行),也可以是一个字符串表示匹配的内容替换成什么。
注意:replace的第二个参数如果是回调函数,是匹配一次执行一次!!!!
举个栗子:如果第二个参数是一个字符串
AABB式 处理后 变成 BBAA 式
var reg = /(\w)\1(\w)\2/g;
var str = 'aabb';
var retStr = str.replace(reg, "$2$2$1$1");
//$1:第一个子表达式里面的内容
//$2:第二个子表达式里面的内容
//结果:retStr --> bbaa
举个栗子:如果第二个参数是匹配内容后的回调函数
AABB 式 替换后 BBAA式
var str = 'aabb';
var reg = /(\w)\1(\w)\2/g;
var retStr = str.replace(reg, function($, $1, $2) {
console.log(arguments);
// 第一个参数是匹配到的内容,第二个参数是第一个子表达式匹配到的内容,以此类推,然后是匹配的索引位置...
// ["aabb", "a", "b", 0, "aabbccdd", callee:....] //第一次执行时的输出
return $2+$2+$1+$1;
});
实例:the-first-name 处理后 变成 小驼峰式的写法
var reg = /-(\w)/g;
var str = 'the-first-name';
//思路:将 -f、-n 分别替换成 F 、N
str.replace(reg, function($, $1) {
return $1.toUpperCase();
});
属性:
- regexp.ignoreCase
- regexp.global
- regexp.multiline
- regexp.source —— 正则表达式内部的内容
- regexp.lastIndex —— 通常与 exec 方法相搭配使用
var reg = /ab/g;
var str = 'ababab';
console.log(reg.exec(str));
///["ab", index: 0, input: "ababab", groups: undefined]
console.log(reg.lastIndex);
//2
console.log(reg.exec(str));
///["ab", index: 2, input: "ababab", groups: undefined]
console.log(reg.lastIndex);
//4
reg.lastIndex = 0; // 当将游标的位置重置为0后
console.log(reg.lastIndex); // 0
console.log(reg.exec(str)); //游标重置为0了,所以又重头开始匹配
///["ab", index: 0, input: "ababab", groups: undefined]
console.log(reg.lastIndex);
//2
正向预查(正向断言)
正向预查:?=n
如:n1(?=n2):n2 不参与选择,只负责修饰(限定) n1 ,匹配到的内容为 n1 后面紧跟着是 n2 的 n1
// 查询字符串 'abaaaa' 中 后面是b的a
var str = 'abaaaa';
var reg = /a(?=b)/g;
str.match(reg); // ["a"]
非正向预查 ?!n
如:n1(?!n2):n2 不参与选择,只负责修饰 n1,匹配到的内容为 n1 后面紧跟着的不是 n2 的 n1
// 查询字符串 'baaaa' 中 后面不是b的a
var str = 'abaaaa';
var reg = /a(?!b)/g;
str.match(reg);
//["a", "a", "a", "a"]
非贪婪匹配
正则默认是 贪婪匹配 , 就是尽可能多的匹配正则里面的规则
非贪婪匹配:与贪婪匹配相反,就是尽可能少的匹配,能匹配一个,就不会匹配多个
非贪婪匹配只要在量词后面加个 “?” 就可以了~
举个栗子:
//举个栗子:
var str = 'aabca';
//贪婪匹配:
var reg1 = /a+/g;
str.match(reg1);
//["aa", "a"]
//非贪婪匹配:
var reg2 = /a+?/g;
str.match(reg2);
//["a", "a", "a"]
习题:
1. 检验一个字符串首/尾是否包含数字
var reg = /^\d|\d$/;
2. 检验一个字符串首尾是否都含有数字
var reg = /^\d[\s\S]*\d$/;
3. 匹配字符串中连续的4个相同的字符(如 aaaa、ffff等)
var reg = /(\w)\1\1\1/g;
var str = 'aaaaddbfebbbbi';
str.match(reg); //["aaaa", "bbbb"]
4. 匹配字符串中AABB格式的字符(如 aabb 、ccdd等)
var reg = /(\w)\1(\w)(?!\1)\2/g; //(?!\1) --> 第二个子表达式匹配的内容不与第一个子表达式相同
var str = 'aabbeeiccddffff';
str.match(reg); //["aabb", "ccdd"]
5. 字符串AABB式替换成BBAA式
var reg = /(\w)\1(\w)(?!\1)\2/g;
var str = 'aabbeeiccddffff';
str.replace(reg, "$2$2$1$1"); //bbaaeeiddccffff
6. 将the-first-name替换成theFirstName
var reg = /-(\w)/g;
var str = 'the-first-name';
str.replace(reg, function($, $1) { return $1.toUpperCase()}); //theFirstName
7. 将字符串 "aaaaaabbbbbbbccddd" 替换成 "abcd"
var str = "aaaaaabbbbbbbccddd";
var reg = /(\w)\1*/g;
str.replace(reg, "$1"); //abcd
8. 将字符串 100000000 转换为 从后面往前面查每隔三位加一个“.” , 即 100.000.000
var reg = /(?=((\d{3})+$))/;
// (\d{3})+$ ————> 以3的倍数个结尾的数字
// (?=((\d{3})+$))————> 正向预查:匹配一个位置,这个位置后面有3或3的倍数个数字
var str = "100000000";
var str2 = "10000000";
str2.replace(reg, "."); //结果:"10.000.000
str.replace(reg, "."); //结果:".100.000.000
//上面的正则没有考虑到字符串的长度如果是3的倍数的话,会在开头的位置也加一个“.”
//(\B) 非单词边界
//?=(\B)((\d{3})+$) 匹配一个位置:这个位置是非单词边界并且后面有3或者3的倍数个数字
var reg = /(?=(\B)((\d{3})+$))/;
var str = "100000000";
str.replace(reg, "."); //100.000.000