正则表达式
↓↓↓↓↓↓↓↓↓直接预览目录中图片版笔记即可,文字版可用于复制
目录
↑ ↑ ↑ ↑ ↑ ↑直接预览目录中图片版笔记即可,文字版可用于复制
来自 https://juejin.cn/post/6844903487155732494
图片版笔记
正则表达式是匹配模式,要么匹配字符,要么匹配位置。
第一章 正则表达式字符匹配攻略
1 两种模糊匹配
var string = "……,……,……"
regex = / ... /
//正则表达式
string.match(regex)
//=> ["a1b", "a2b", "a3b"]
1.1 横向模糊匹配
横向模糊匹配:/ad{2,10}c/
(横向模糊指的是,一个正则可匹配的字符串的长度不是固定的,可以是多种情况的。)
(表示匹配这样一个字符串:第一个字符是“a”,接下来是2到5个字符“b”,最后是字符“c”)
量词: {m,n}
(表示此字母连续出现最少m次,最多n次)
(量词在正则表达式中使用时可以限制前方字符的长度)
简写形式:
{m,} 表示至少出现m次。
{m} 等价于{m,m},表示出现m次。
? 等价于{0,1},表示出现或者不出现。记忆方式:问号的意思表示,有吗?
- 等价于{1,},表示出现至少一次。记忆方式:加号是追加的意思,得先有一个,然后才考虑追加。
-
等价于{0,},表示出现任意次,有可能不出现。记忆方式:看看天上的星星,可能一颗没有,可能零散有几颗,可能数也数不过来。
var regex = /ab{2,5}c/g; var string = "abc abbc abbbc abbbbc abbbbbc abbbbbbc"; console.log( string.match(regex) ); // => ["abbc", "abbbc", "abbbbc", "abbbbbc"]
全局匹配:/g
(在目标字符串中按顺序找到满足匹配模式的所有子串,强调的是“所有”,而不只是“第一个”。)
1.2 纵向模糊匹配
纵向模糊匹配:/a[123]c/
(纵向模糊指的是,一个正则匹配的字符串,具体到某一位字符时,它可以不是某个确定的字符,可以有多种可能。)
(表示该字符是可以字符“1”、“2”、“3”中的任何一个。)
字符组:[abv123%]
(字符组在正则表达式中使用时可以代替一个字符)
范围表示法: [1-6a-fG-M]
连字符:-
(来省略和简写)
需要匹配连字符怎么办?
要匹配“a”、“-”、“z”这三者中任意一个字符
[-az]或[az-]或[a-z]。连字符要么放在开头,要么放在结尾,要么反斜杠写在连字符前转义。
排除字符组:[^abc]
(表示是一个除"a"、“b”、"c"之外的任意一个字符。)
脱字符:^
\d就是[0-9]。表示是一位数字。记忆方式:其英文是digit(数字)。
\D就是[^0-9]。表示除数字外的任意字符。
\w就是[0-9a-zA-Z_]。表示数字、大小写字母和下划线。记忆方式:w是word的简写,也称单词字符。
\W是[^0-9a-zA-Z_]。非单词字符。
\s是[ \t\v\n\r\f]。表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页符。记忆方式:s是space character的首字母。
\S是[^ \t\v\n\r\f]。 非空白符。
.就是[^\n\r\u2028\u2029]。通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。记忆方式:想想省略号…中的每个点,都可以理解成占位符,表示任何类似的东西。
匹配任意字符:
[\d\D]、[\w\W]、[\s\S]和[^]
贪婪匹配和惰性匹配
贪婪匹配
(正则 /\d{2,5}/ ,表示数字连续出现2到5次。会匹配2位、3位、4位、5位连续数字。)
(但是其是贪婪的,它会尽可能多的匹配。)
惰性匹配,就是尽可能少的匹配:
⭐( /\d{2,5}?/ 表示,虽然2到5次都行,当2个就够的时候,就不在往下尝试了,只会匹配2位。)
通过在量词后面加个问号 ? 就能实现惰性匹配,因此所有惰性匹配情形如下:
{m,n}?
{m,}?
??
+?
*?
多选分支
具体形式如下:(p1|p2|p3),其中p1、p2和p3是子模式,用 |(管道符)分隔,表示其中任何之一。
用管道符链接的多个子模式就是多选分支,她是惰性匹配。
例如要匹配"good"和"nice"可以使用 /good|nice/。测试如下:
var regex = /good|nice/g;
var string = "good idea, nice try.";
console.log( string.match(regex) );
// => ["good", "nice"]
但有个事实我们应该注意,比如我用/good|goodbye/,去匹配"goodbye"字符串时,结果是"good":
var regex = /good|goodbye/g;
var string = "goodbye";
console.log( string.match(regex) );
// => ["good"]
而把正则改成/goodbye|good/,结果是:
var regex = /goodbye|good/g;
var string = "goodbye";
console.log( string.match(regex) );
// => ["goodbye"]
也就是说,分支结构也是惰性的,即当前面的匹配上了,后面的就不再尝试了。
⭐(/goodbye|good/表示匹配goodbye或good都可以,但匹配到goodbye后就不再判断是否有good了)
ex:匹配时间
以24小时制为例。
要求匹配:
23:59
02:07
分析:
共4位数字,第一位数字可以为[0-2]。
当第1位为2时,第2位可以为[0-3],其他情况时,第2位为[0-9]。
第3位数字为[0-5],第4位为[0-9]
正则如下:
var regex = /^([01][0-9]|[2][0-3]):[0-5][0-9]$/;
console.log( regex.test("23:59") );
console.log( regex.test("02:07") );
// => true
// => true
如果也要求匹配7:9,也就是说时分前面的0可以省略。
此时正则变成:
var regex = /^(0?[0-9]|1[0-9]|[2][0-3]):(0?[0-9]|[1-5][0-9])$/;
console.log( regex.test("23:59") );
console.log( regex.test("02:07") );
console.log( regex.test("7:9") );
// => true
// => true
// => true
⭐(?可以直接使用表示前方的数字可以省略)
\字符需要转义
[^\:<>|"?\r\n/]:
表示合法字符
要求匹配:
F:\study\javascript\regex\regular expression.pdf
F:\study\javascript\regex
F:\study\javascript
F:
var regex = /[a-zA-Z]:\([\:<>|"?\r\n/]+\)([^\:<>|"?\r\n/]+)?$/;
console.log( regex.test(“F:\study\javascript\regex\regular expression.pdf”) );
console.log( regex.test(“F:\study\javascript\regex\”) );
console.log( regex.test(“F:\study\javascript”) );
console.log( regex.test(“F:\”) );
// => true
// => true
// => true
// => true
其中,JS中字符串表示\时,也要转义。
比如说匹配输入串
A: 101000000000100
使用 1.1 将会匹配到1010000000001,匹配方法: 先匹配至输入串A的最后,然后向前匹配,直到可以匹配到1,称之为贪婪匹配。
使用 1.?1 将会匹配到101,匹配方法: 匹配下一个1之前的所有字符,称之为非贪婪匹配。
第二章 正则表达式位置匹配攻略
1.什么是位置呢?
位置是相邻字符之间的位置。比如,下图中箭头所指的地方:
2.如何匹配位置呢?
在ES5中,共有6个锚字符:
^ $ \b \B (?=p) (?!p)
2.1 ^和$
^(脱字符)匹配开头,在多行匹配中匹配行开头。
$(美元符号)匹配结尾,在多行匹配中匹配行结尾。
比如我们把字符串的开头和结尾用"#"替换(位置可以替换成字符!):
var result = "hello".replace(/^|$/g, '#');
console.log(result);
// => "#hello#"
多行匹配模式时,二者是行的概念,这个需要我们的注意:
var result = "I\nlove\njavascript".replace(/^|$/gm, '#');
console.log(result);
/*
#I#
#love#
#javascript#
*/
也就是说,每行都有开头和结尾被匹配。
2.2 \b和\B
\b是单词边界,具体就是\w和\W之间的位置,也包括\w和^之间的位置,也包括\w和KaTeX parse error: Undefined control sequence: \b at position 38: …esson_01.mp4"中的\̲b̲,如下: var result…之间的位置,必须是/w与开头或结尾之间产生\b
知道了\b的概念后,那么\B也就相对好理解了。
\B就是\b的反面的意思,非单词边界。
具体说来就是\w与\w、\W与\W、^与\W,\W与$之间的位置。
把所有\B替换成"#":
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"
2.3 (?=p)和(?!p)
(?=p),其中p是一个子模式,即p前面的位置。
比如(?=l),表示’l’字符前面的位置,例如:
var result = "hello".replace(/(?=l)/g, '#');
console.log(result);
// => "he#l#lo"
而(?!p)就是(?=p)的反面意思,比如:
var result = "hello".replace(/(?!l)/g, '#');
console.log(result);
// => "#h#ell#o#"
二者的学名分别是positive lookahead和negative lookahead。
中文翻译分别是正向先行断言和负向先行断言。
ES6中,还支持positive lookbehind和negative lookbehind。
具体是(?<=p)和(?<!p)。
锚字符指定正则中相对应位置上有什么
不匹配任何东西的正则:/.^/
因为此正则要求只有一个字符,但该字符后面是开头。
Ex:
(?=.[0-9])任意字符串后有一数字
(?=.[a-z])任意字符串后有一小写字母
(?=.*[A-Z])任意字符串后有一大写字母
不匹配任何东西的正则/.^/
开头位置/(?=^)/
非开头位置/(?!^)/
包含数字大小写字母的6-12位密码:
“至少包含两种字符”的意思就是说,不能全部都是数字,也不能全部都是小写字母,也不能全部都是大写字母:
var reg = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)
^[0-9A-Za-z]{6,12}$/;
console.log( reg.test("1234567") ); // false 全是数字
console.log( reg.test("abcdef") ); // false 全是小写字母
console.log( reg.test("ABCDEFGH") ); // false 全是大写字母
console.log( reg.test("ab23C") ); // false 不足6位
console.log( reg.test("ABCDEF234") ); // true 大写字母和数字
console.log( reg.test("abcdEF234") ); // true 三者都有
同时包含两种类型字符,同时包含数字、小写字母和大写字母:
var reg = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[0-9A-Za-z]{6,12}$/;
console.log( reg.test("1234567") ); // false 全是数字
console.log( reg.test("abcdef") ); // false 全是小写字母
console.log( reg.test("ABCDEFGH") ); // false 全是大写字母
console.log( reg.test("ab23C") ); // false 不足6位
console.log( reg.test("ABCDEF234") ); // true 大写字母和数字
console.log( reg.test("abcdEF234") ); // true 三者都有