xiaokeqi / i-learned

1 stars 0 forks source link

js正则表达式 #6

Open xiaokeqi opened 5 years ago

xiaokeqi commented 5 years ago

JavaScript API

RegExp test // 用来查看正则表达式与指定的字符串是否匹配, 返回true false
RegExp exec // 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null
String search // 方法执行正则表达式和 String 对象之间的一个搜索匹配,如果匹配成功,则 search() 返回正则表达式在字符串中首次匹配项的索引;否则,返回 -1。
String match //方法检索返回一个字符串匹配正则表达式的的结果。
String replace //方法返回一个由替换值(replacement)替换一些或所有匹配的模式(pattern)后的新字符串。模式可以是一个字符串或者一个正则表达式,替换值可以是一个字符串或者一个每次匹配都要调用的回调函数。
xiaokeqi commented 5 years ago

RegExp test

var regx = /\d/;
var str = 'abc1234';
regx.test(str); // true 匹配str字符串中是否含有数字
xiaokeqi commented 5 years ago

RegExp exec

var regx = /\d/g;
var str = 'abc1234';
regx.exec(str);// ["1", index: 3, input: "abc1234", groups: undefined]
var regx = /(\d)/g;
var str = 'abc1234';
regx.exec(str);// ["1", "1", index: 3, input: "abc1234", groups: undefined]
var regx = /(\d)(\d)/g;
var str = 'abc1234';
regx.exec(str);// ["12", "1", "2", index: 3, input: "abc1234", groups: undefined]

exec方法会匹配所有的组和子组,返回一个类数组结构。

-------看黑板------以上只是讲解了下exec的基本用法。更强大的功能如下: exec通过运用lastIndex接着上一次匹配结果,继续匹配。 例子如下:

var str = '12.45.df.452';
var reg = /(\d+)/g; //注,必须带g哦,要不然lastIndex一直是0。
reg.exec(str);
reg.lastIndex; // 2
reg.exec(str);
reg.lastIndex;// 5
reg.exec(str);
reg.lastIndex;// 12
reg.exec(str);// null
reg.lastIndex;// 0

比如,第一次匹配了“12”,开始下标是0,共2个字符,因此这次匹配结束的位置是1,下次开始匹配的位置是2。从上面代码可以看出,在使用exec时,经常需要配合while使用,如下

var str = '12.45.df.452';
var reg = /(\d+)/g; //注,必须带g哦,要不然lastIndex一直是0。
while(result = reg.exec(str)){
    console.log(result, reg.lastIndex);
}
xiaokeqi commented 5 years ago

String search

var regx=/\d/g;
var str='abc1234';
str.search(regx);// 3

匹配成功返回索引值,否则返回-1 注:search中的参数,必须为正则表达式,若输入字符串,则会将其强制转为正则表达式,如

var string = "2017.06.27";
console.log( string.search(".") );// => 0
xiaokeqi commented 5 years ago

String match

var regx = /\d/;
var str = 'abc1234';
str.match(regx);//["1", index: 3, input: "abc1234", groups: undefined]
var regx = /\d/g;
var str = 'abc1234';
str.match(regx);//["1", "2", "3", "4"]

带g与不带g,返回值是差别很大的。

没有g,返回的是标准匹配格式,即,数组的第一个元素是整体匹配的内容,接下来是分组捕获的内容,然后是整体匹配的第一个下标,最后是输入的目标字符串。

有g,返回的是所有匹配的内容

当没有匹配时,不管有无g,都返回null。

注:match参数必须为正则表达式,若传入字符串,则被转为正则表达式,如

var string = "2017.06.27";
console.log( string.match(".") );// => ["2", index: 0, input: "2017.06.27"]
xiaokeqi commented 5 years ago

String 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"]
var string = "2017-06-26";
string.replace(/-/g, "/") ; //2017/06/26

var string = "2017-06-26";
string.replace(/-/, "/") ;//"2017/06-26

哦,以上只是基础用法,更强大的在👇

当replace第二个参数是字符串时,某些字符串有特殊含义,如下:

$1,$2,$3.....$99 匹配第1-99个分组里捕获的文本
$& 匹配到的子串文本
$`匹配到的子串的左边文本
$'匹配到的子串的右边文本
$$美元符号

举个例子

例如把“2,3,5”,变成“5=2+3”
"2,3,5".replace(/(\d+),(\d+),(\d+)/,"$3=$1+$2");//
例如把“2,3,5”变成“222,333,555”
“2,3,5”.replace(/(\d+)/g, '$1$1$1')
或 '2,3,5'.replace(/(\d+)/g,'$&$&$&')

当第二个参数是函数时,其回调中参数如下:

"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"]
xiaokeqi commented 5 years ago

String split

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"]

注意:

split看起来不起眼,但要主要的地方有两个。 一,它可以有两个参数,第二个参数表示数组的最大长度。

var string = "html,css,javascript";
console.log( string.split(/,/, 2) );// =>["html", "css"]

二, 正则使用分组时,结果数组中是包含分隔符的:

var string = "html,css,javascript";
console.log( string.split(/(,)/) );
// =>["html", ",", "css", ",", "javascript"]
xiaokeqi commented 5 years ago

修饰符

g (global)全局匹配,即找到所有匹配的
i (ignoreCase) 忽略字母大小写
xiaokeqi commented 5 years ago

----------敲黑板 ----------js中正则表达式的运用阐述完了 ----------下面将主要讲解,如何写正则表达式

xiaokeqi commented 5 years ago

量词

{m,n}  表示连续出现最少m次,最多n次
{m,}    至少出现m次
{m}     出现m次
?       等价于{0,1} 最多1次
+        等价于{1, } 至少一次
*         等价于{0,}  任意次,也可不出现
xiaokeqi commented 5 years ago

字符

[abc]   表示可以是字符a,b,c中的任何一个,取其一
^   【字符组】的第一位放^,表示求反概念,如[^abc],除a,b,c之外的字符。字符组即[]
[a-z]  范围表示法,匹配abcd...xyz。若要匹配-,a,z,,怎么写?[az-]或[-az]

常见的描述字符的符号,如下:

\d  等价于[0-9]
\D 等价于[^0-9]
\w 等价于[0-9a-zA-Z_] 表示数字、大小写字母、下划线
\W 等价于[^0-9a-zA-Z_] 非单词字符
\s [\t\v\n\r\f] 空白符,可通过space character记忆
\S 非空白符
.  [^\n\r\u2028\u2029]通配符,表示几乎任意字符。

匹配任意字符呢?我们可以这样写[\d\D],[\w\W],[\s\S]和[^]

xiaokeqi commented 5 years ago

贪婪匹配和惰性匹配

什么是贪婪?比如你送给我5个苹果,我就要吃掉5个,不论撑不撑着我,我都要吃掉。而惰性呢?无论你给我几个苹果,我只要我需要的个数。多的,我全不要。我就可以不用洗那么多的苹果了,够懒吧? 在正则表达式中,贪婪与惰性,匹配如下:

var regx = /\w{2,5}/g;
var str = 'ab abc abcd abcde abcdef';
str.match(regx);// [ab, abc, abcd, abcde, abcde]

js中默认的是贪婪的。仔细看上面的例子,\w{2, 5},匹配2个就够了,但子组里面,我们发现,若字符串中有5个,我就要匹配5个,即abcde

但有时候贪婪不是好事,我们有时候需要惰性匹配,即2个就够了,我就只匹配两个 如下:

var regx = /\w{2,5}?/g;
var str = 'ab abc abcd abcde abcdef';
str.match(regx);//["ab", "ab", "ab", "cd", "ab", "cd", "ab", "cd", "ef"]

惰性匹配只要匹配到符合自己的字符,就结束本次匹配,去匹配新的

正则表达式中,通过在量词后加个?实现惰性匹配。

注意是量词后加?,如下:

{m,n}?
{m,}?
??
+?
*?
xiaokeqi commented 5 years ago

多选分支 |

以前,我一直以为,| 必须要带(),才能一组组的匹配,原来,我理解错了概念,例子如下:

var regx = /abc|123/g;
var str = 'abcde';
str.match(regx); // ['abc']

这里并不是 c、1是或的关系,而是abc 与 123 是或的关系

xiaokeqi commented 5 years ago

匹配位置

位置是相邻字符之间的位置。如: image js中匹配位置的字符有如下: ^ $ \b \B (?=p) (?!p)

^ 和 $

^ 匹配开头,在多行匹配中,匹配行开头 $ 匹配结尾,在多行匹配中,匹配行结尾

var result = "hello".replace(/^|$/g, '#');
console.log(result); 
var result = "I\nlove\njavascript".replace(/^|$/gm, '#');
console.log(result);
/*
#I#
#love#
#javascript#
*/

\b 和 \B \b是单词边界,具体就是\w和\W之间的位置,也包括\w和^之间的位置,也包括\w和$之间的位置。 首先,我们知道,\w是字符组[0-9a-zA-Z]的简写形式,即\w是字母数字或者下划线的中任何一个字符。而\W是排除字符组[^0-9a-zA-Z]的简写形式,即\W是\w以外的任何一个字符。

var result = "[JS] Lesson_01.mp4".replace(/\b/g, '#');
console.log(result); // => "[#JS#] #Lesson_01#.#mp4#"

此时我们可以看看"[#JS#] #Lesson_01#.#mp4#"中的每一个"#",是怎么来的。

\B 就是\b取反的意思,即\w与\w、\W与\W、^与\W,\W与$之间的位置。

var result = "[JS] Lesson_01.mp4".replace(/\B/g, '#');
console.log(result); 
// => "#[J#S]# L#e#s#s#o#n#_#0#1.m#p#4"

(?=p) 和(?!p) (?=p),其中p是一个子模式,即p前面的位置。 比如(?=l),表示'l'字符前面的位置,例如:

var result = "hello".replace(/(?=l)/g, '#');
console.log(result); 
// => "he#l#lo"

而(?!p)就是(?=p)的反面意思,即非p字母前面的位置。比如:

var result = "hello".replace(/(?!l)/g, '#');
console.log(result); 
// => "#h#ell#o#"

(?<=p) 和 (?<!p) es6中新增的正则表达式。(?<=p) ,即p后面的位置。(?<!p) 非p字母后面的位置

var result = "hello".replace(/(?<=l)/g, '#');
console.log(result); // hel#l#o

var result = "hello".replace(/(?<!l)/g, '#');
console.log(result); //#h#e#llo#
xiaokeqi commented 5 years ago

反向引用

写一个正则,匹配如下三种格式

2019-07-23
2019/07/23
2019.07.23

最先想到的正则是:

var regex = /\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/;
var string1 = "2017-06-12";
var string2 = "2017/06/12";
var string3 = "2017.06.12";
var string4 = "2016-06/12";
console.log( regex.test(string1) ); // true
console.log( regex.test(string2) ); // true
console.log( regex.test(string3) ); // true
console.log( regex.test(string4) ); // true

但也匹配到了2016-06/12这样的数据情况。此时我们可以通过使用反向引用来解决。 反向引用只能引用之前出现的分组 /\d{4}(-|\/|.)\d{2}\1\d{2}/ 那如果括号嵌套怎么办。以左开括号为准

var regex = /^((\d)(\d(\d)))\1\2\3\4$/;
var string = "1231231233";
console.log( regex.test(string) ); // true
console.log( RegExp.$1 ); // 123
console.log( RegExp.$2 ); // 1
console.log( RegExp.$3 ); // 23
console.log( RegExp.$4 ); // 3
xiaokeqi commented 5 years ago

例子

验证密码 1.只能是数字、字母、下划线,长度不限制 /^\w+$/ 2.允许小写字母a-z、大写字母A-Z、数字0-9、下划线_、连接符-,且长度在6-18位数 /^(\w|-){6,18}$/ 3.必须包含数字+小写字母+大写字母的密码,且长度在8-10位之间 /^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$/

xiaokeqi commented 5 years ago

参考文档:https://juejin.im/post/5965943ff265da6c30653879#heading-38

xiaokeqi commented 4 years ago

1、var s1 = "get-element-by-id"; 给定这样一个连字符串,写一个function转换为驼峰命名法形式的字符串 getElementById

s1.replace(/-\w/g,function(x){return x.slice(1).toUpperCase});

xiaokeqi commented 4 years ago

判断字符串是否包含数字 /\d/g.test(str)

xiaokeqi commented 4 years ago

判断电话号码 /^1[34578]\d{9}$/

xiaokeqi commented 4 years ago

实现千分位分割 /(?!^)(?=(\d{3})+$)/g