正则的查缺补漏

多选分支|

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"]
posted @ 2019-01-12 15:11  猫神甜辣酱  阅读(426)  评论(0编辑  收藏  举报