正则的查缺补漏
多选分支|
var regex = /good|goodbye/g;
var string = "goodbye";
console.log( string.match(regex) );
// => ["good"]
也就是说分支也是惰性的,当前匹配上了,后面的不再尝试了
var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
var string = "#ffbbad #Fc01DF #FFF #ffE";
console.log( string.match(regex) );
// => ["#ffbbad", "#Fc01DF", "#FFF", "#ffE"]
//所以应该把{6} 写前面 匹配少到匹配多
(?=p) 和(?!p) 零宽断言
零宽断言:零宽度的匹配,匹配到的内容不保存在匹配结果中,最终匹配的结果只是一个位置。
Javascript 只支持零度先行断言
?=p 表示p前面的位置 (理解^) 先行断言
?!p 表示?=p的反面意思 负向先行断言
零宽断言返回的是位置而不是字符
console.log("abcdefg".match(/ab(?=cd)/g));
console.log("abcdefg".match(/(?=cd)efg/g));//没匹配上返回null
console.log("abcdefg".match(/ab(?=cd)cdefg/g));
var result = "hello".replace(/(?!l)/g, '#');
console.log(result);
// => "#h#ell#o#"
找到所有的.min.css文件的文件名
let str = "a.min.css;.min.css;.css;min.css;b.css;c.min.js;d.css;e.a.min.css";
console.log(str.match(/\w+(?=\.min\.css)/g));
测试一个文件是否是.css后缀,但是不能用.min.css
var reg=/^(?!.*\.min\.css$).+\.css$/;
reg.test('a.min.css'); // false
reg.test('.min.css'); // false
reg.test('.css'); // false
reg.test('min.css'); // true
reg.test('b.css'); // true
reg.test('c.mining.css'); // true
数字的千位分隔符
'12345678'.replace(/\B(?=(\d{3})+\b)/g,',')
(?=.*[0-9])
翻译 : 有多个任意字符后面必须包含个数字(至少包含)
(?!^[0-9]{6,12}$)
翻译: 不能全部是数字(不能全部)
\w
单词\w [0-9a-zA-Z_]
\b 单词边界
分组
()
match [i] 查看每一个组的数值
$1 $2 $3 记得加引号包起来
构造函数的全局属性$1至$9来获取
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
console.log(string.replace(regex, "$1 / $2 / $3"));
非捕获分组
(?:p)
var regex = /(?:ab)+/g;
var string = "ababa abbb ababab";
console.log( string.match(regex) );
// => ["abab", "ab", "ababab"]
var data = 'windows 98 is ok';
data.match(/windows (?:\d+)/); // ["windows 98"]
data.match(/windows (\d+)/); // ["windows 98", "98"]
它跟() 不同的地方在于,不作为子匹配返回
找到每个单词的首字母
'my name is epeli'.replace(/(?:^|\s)\w/g, c => c.toUpperCase())
反向引用
\1, \2 ,\3 ...
/([a-z]\d)-\d(123)\1/
指的是每一组小括号就是所谓的一组 \1 就是 [a-z]\d 第一个分组的匹配
当我们不需要使用分组引用和反向引用时,此时可以使用非捕获分组
/^[+-]?(\d+\.\d+|\d+|\.\d+)$/
可以修改成:
/^[+-]?(?:\d+\.\d+|\d+|\.\d+)$/
位置字符和字符序列优先级要比竖杠高
^(abc|bcd)$ 要用括号包起来
^([abc]{3})+$
字符组中的元字符
var string = "^$.*+?|\\/[]{}=!:-,";
var regex = /[\^$.*+?|\\/\[\]{}=!:\-,]/g;
console.log(string.match(regex));
其中[] ^ - 需要转义
竖杠的优先级最低,即最后运算。
另外关于元字符转义问题,当自己不确定与否时,尽管去转义,总之是不会错的。
优化
独立出确定字符
/a+/ 可以修改成 /aa*/
提取公共部分
比如/^abc|^def/,修改成/^(?:abc|def)/。
又比如/this|that/,修改成/th(?:is|at)/。
减少分支的数量,缩小它们的范围
/red|read/,可以修改成/rea?d/。此时分支和量词产生的回溯的成本是不一样的。但这样优化后,可读性会降低的。
正则表达式的四种操作
正则表达式是匹配模式
正则 gi g全局i区分大小写 m多行匹配
exec
注意分组的参数
若检索成功,返回匹配的数组,否则返回null
let result = /len/g.exec('hello len!!');
//[ 'len', index: 6, input: 'hello len!!' ]
test
test整体匹配时需要使用^和$
若匹配成功返回true否则返回false
let str = "hello leo!";
let res = /leo/.test(str); // true
search
若检索成功,返回第一个与正则对象匹配的字符串的起始位置,否则返回-1
let str = "hello leo!";
let res = str.search(/leo/g); // 6
match
匹配记得加/g
若检索成功,返回与reg匹配的所有结果的一个数组,否则返回null
str.match(regSS)
验证(最常用的是test
)
判断一个字符串中是否有数字
使用 search
~~ 常用来取整,也可以用来转换成数字类型
~~true == 1
~~false == 0
~~"" == 0
~~[] == 0
~~undefined ==0
~~!undefined == 1
~~null == 0
~~!null == 1
~为取反运算符,如果names.indexOf(name)返回值为-1,即names不包含name,那么~-1 = 0。其他值取反后值都不为0。结合!~来判断names是否包含name
var string = "abc123";
console.log( !!~string.search(regex) );
// => true
使用testvar regex = /\d/;
var string = "abc123";
console.log( regex.test(string) );
// => true
使用match
var regex = /\d/;
var string = "abc123";
console.log( !!string.match(regex) );
// => true
使用exec
var regex = /\d/;
var string = "abc123";
console.log( !!regex.exec(string) );
// => true
切分(在js中常用split)
var regex = /,/;
var string = "html,css,javascript";
console.log( string.split(regex) );
// => ["html", "css", "javascript"]
var regex = /\D/;
console.log( "2017/06/26".split(regex) );
console.log( "2017.06.26".split(regex) );
console.log( "2017-06-26".split(regex) );
// => ["2017", "06", "26"]
// => ["2017", "06", "26"]
// => ["2017", "06", "26"]
提取(正则通常要使用分组引用(分组捕获)最常用的是match)
match
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
var string = "2017-06-26";
console.log( string.match(regex) );
// =>["2017-06-26", "2017", "06", "26", index: 0, input: "2017-06-26"]
exec
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
var string = "2017-06-26";
console.log( regex.exec(string) );
// =>["2017-06-26", "2017", "06", "26", index: 0, input: "2017-06-26"]
test
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
var string = "2017-06-26";
regex.test(string);
console.log( RegExp.$1, RegExp.$2, RegExp.$3 );
// => "2017" "06" "26"
search
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
var string = "2017-06-26";
string.search(regex);
console.log( RegExp.$1, RegExp.$2, RegExp.$3 );
// => "2017" "06" "26"
replace
var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
var string = "2017-06-26";
var date = [];
string.replace(regex, function(match, year, month, day) {
date.push(year, month, day);
});
console.log(date);
// => ["2017", "06", "26"]
替换(replace)
相关API(字符串四种支持正则)
String#search
String#split
String#match
String#replace
RegExp#test
RegExp#exec
注意点
match 返回结果的格式,与正则对象是否有修饰符g有关
没有g,返回的是标准匹配格式,数组的第一个元素是整体匹配的内容
有g,返回的所有匹配的内容
exec方法就能解决这个问题,它能接着上一次匹配后继续匹配
正则实例lastIndex属性,表示下一次匹配开始的位置
var string = "2017.06.27";
var regex2 = /\b(\d+)\b/g;
console.log( regex2.exec(string) );
console.log( regex2.lastIndex);
console.log( regex2.exec(string) );
console.log( regex2.lastIndex);
console.log( regex2.exec(string) );
console.log( regex2.lastIndex);
console.log( regex2.exec(string) );
console.log( regex2.lastIndex);
// => ["2017", "2017", index: 0, input: "2017.06.27"]
// => 4
// => ["06", "06", index: 5, input: "2017.06.27"]
// => 7
// => ["27", "27", index: 8, input: "2017.06.27"]
// => 10
// => null
// => 0
从上述代码看出,在使用exec时,经常需要配合使用while循环
split
它可以有两个参数,第二个参数表示数组的最大长度
var string = "html,css,javascript";
console.log( string.split(/,/, 2) );
// =>["html", "css"]
replace(很强大,单独拿出来)
这是因为它的第二个参数,可以是字符串,也可以是函数。
第二个参数是字符串时
$1,$2,...,$99 匹配第1~99个分组里捕获的文本
$& 匹配到的子串文本
$` 匹配到的子串的左边文本
$' 匹配到的子串的右边文本
$$ 美元符号
例如,把"2,3,5",变成"5=2+3":
var result = "2,3,5".replace(/(\d+),(\d+),(\d+)/, "$3=$1+$2");
console.log(result);
// => "5=2+3"
又例如,把"2,3,5",变成"222,333,555":
var result = "2,3,5".replace(/(\d+)/g, "$&$&$&");
console.log(result);
// => "222,333,555"
再例如,把"2+3=5",变成"2+3=2+3=5=5":
var result = "2+3=5".replace(/=/, "$&$`$&$'$&");
console.log(result);
// => "2+3=2+3=5=5"
当第二个参数是函数时,我们需要注意该回调函数的参数具体是什么:
"1234 2345 3456".replace(/(\d)\d{2}(\d)/g, function(match, $1, $2, index, input) {
console.log([match, $1, $2, index, input]);
});
// => ["1234", "1", "4", 0, "1234 2345 3456"]
// => ["2345", "2", "5", 5, "1234 2345 3456"]
// => ["3456", "3", "6", 10, "1234 2345 3456"]
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬