当前位置:网站首页>正则笔记(1)- 正则表达式字符匹配攻略
正则笔记(1)- 正则表达式字符匹配攻略
2022-08-02 03:23:00 【星雨668】
1. 正则表达式字符匹配
正则表达式是匹配模式,要么匹配字符,要么匹配位置。 请记住这句话。
1.1.两种模糊匹配
如果正则只有精确匹配是没多大意义的,比如 /hello/,也只能匹配字符串中的 “hello” 这个子串。
var regex = /hello/;
console.log( regex.test("hello")); // true
正则表达式之所以强大,是因为其能实现模糊匹配。
而模糊匹配,有两个方向上的“模糊”:横向模糊和纵向模糊。
1.1.1.横向模糊匹配
横向模糊指的是,一个正则可匹配的字符串的长度不是固定的,可以是多种情况的。
其实现的方式是使用量词。譬如 {m,n},表示连续出现最少 m 次,最多 n 次。
比如正则 /ab{2,5}c/ 表示匹配这样一个字符串:第一个字符是 “a”,接下来是 2 到 5 个字符 “b”,最后
是字符 “c”。
测试如下:
var regex = /ab{2,5}c/g;
var string = "abc abbc abbbc abbbbc abbbbbc";
console.log(string.match(regex));
// ['abbc', 'abbbc', 'abbbbc', 'abbbbbc']
注意:案例中用的正则是/ab{2,5}c/g,后面多了g,它是正则的一个修饰符。表示全局匹配,即在目标字符串中按顺序找到满足匹配模式的所有子串,强调的是“所有”,而不只是“第一个”。g是单词global的首字母
1.1.2.纵向模糊匹配
纵向模糊指的是,一个正则匹配的字符串,具体到某一位字符时,它可以不是某个确定的字符,可以有多种
可能。
其实现的方式是使用字符组。譬如 [abc],表示该字符是可以字符 “a”、“b”、“c” 中的任何一个。
比如 /a[123]b/ 可以匹配如下三种字符串: “a1b”、“a2b”、“a3b”。
测试如下:
var regex = /a[123]b/g;
var string = "a0b a1b a2b a3b a4b";
console.log(string.match(regex));
// ['a1b', 'a2b', 'a3b']
1.2.字符租
需要强调的是,虽叫字符组(字符类),但只是其中一个字符。
例如 [abc],表示匹配一个字符,它可以是 “a”、“b”、“c” 之一。
1.2.1.范围表示法
如果字符组里的字符特别多的话,怎么办?可以使用范围表示法。
比如 [123456abcdefGHIJKLM],可以写成 [1-6a-fG-M]。用连字符 - 来省略和简写。
因为连字符有特殊用途,那么要匹配 “a”、“-”、“z” 这三者中任意一个字符,该怎么做呢?
不能写成 [a-z],因为其表示小写字符中的任何一个字符。
可以写成如下的方式:[-az] 或 [az-] 或 [a-z]。
即要么放在开头,要么放在结尾,要么转义。总之不会让引擎认为是范围表示法就行了。
1.2.2.排除字符组
纵向模糊匹配,还有一种情形就是,某位字符可以是任何东西,但就不能是 “a”、“b”、“c”。
此时就是排除字符组(反义字符组)的概念。例如 [^abc],表示是一个除 “a”、“b”、"c"之外的任意一个字 符。字符组的第一位放 ^(脱字符),表示求反的概念。
当然,也有相应的范围表示法。
1.2.3.常见的简写形式
有了字符组的概念后,一些常见的符号我们也就理解了。因为它们都是系统自带的简写形式。
\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] 和 [^] 中任何的一个。
1.3.量词
量词也称重复。掌握 {m,n} 的准确含义后,只需要记住一些简写形式。
1.3.1.简写形式
{m,} 表示至少出现m次。
{m} 等价于{m,m},表示出现m次。
? 等价于{0,1},表示出现或者不出现。记忆方式:问号的意思表示,有吗?
+ 等价于{1,},表示出现至少一次。记忆方式:加号是追加的意思,得先有一个,然后才考虑追加。
* 等价于{0,},表示出现任意次,有可能不出现。记忆方式:看看天上的星星,可能一颗没有,可能零散有几颗,可能数也数不过来。
1.3.2.贪婪匹配与惰性匹配
看出如下例子:
var regex = /\d{2,5}/g;
var string = "123 1234 12345 123456";
console.log(string.match(regex));
// ['123', '1234', '12345', '12345']
其中正则 /\d{2,5}/,表示数字连续出现 2 到 5 次。会匹配 2 位、3 位、4 位、5 位连续数字。
但是其是贪婪的,它会尽可能多的匹配。你能给我 6 个,我就要 5 个。你能给我 3 个,我就要 3 个。
反正只要在能力范围内,越多越好。
我们知道有时贪婪不是一件好事。而惰性匹配,就是尽可能少的匹配:
var regex = /\d{2,5}?/g;
var string = "123 1234 12345 123456";
console.log(string.match(regex));
// ['12', '12', '34', '12', '34', '12', '34', '56']
其中 /\d{2,5}?/ 表示,虽然 2 到 5 次都行,当 2 个就够的时候,就不再往下尝试了。
通过在量词后面加个问号就能实现惰性匹配,因此所有惰性匹配情形如下:
{m,n}?
{m,}?
??
+?
*?
对惰性匹配的记忆方式是:量词后面加个问号,问一问你知足了吗,你很贪婪吗?
1.4.多选分支
一个模式可以实现横向和纵向模糊匹配。而多选分支可以支持多个子模式任选其一。
具体形式如下:(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 = "goodbey";
console.log(string.match(regex));
// ['good']
而把正则改成 /goodbye|good/,结果是:
var regex = /goodbye|good/g;
var string = "goodbye";
console.log(string.match(regex));
// ['goodbye']
也就是说,分支结构也是惰性的,即当前面的匹配上了,后面的就不再尝试了。
1.5. 案例分析
匹配字符,无非就是字符组、量词和分支结构的组合使用罢了。
下面找几个例子演练一下(其中,每个正则并不是只有唯一写法):
1.5.1.匹配 16 进制颜色值
要求匹配:
#ffbbad
#Fc01DF
#FFF
#ffE
分析:
表示一个 16 进制字符,可以用字符组 [0-9a-fA-F]。
其中字符可以出现 3 或 6 次,需要是用量词和分支结构。
使用分支结构时,需要注意顺序。
正则如下:
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']
1.5.2.匹配时间
以 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")); // true
console.log(regex.test("02:07")); // 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")); // true
console.log(regex.test("02:07")); // true
console.log(regex.test("7:9")); // true
1.5.3.匹配日期
比如 yyyy-mm-dd 格式为例
要求匹配:
2017-06-10
分析:
年,四位数字即可,可用 [0-9]{4}。
月,共 12 个月,分两种情况 “01”、“02”、…、“09” 和 “10”、“11”、“12”,可用 (0[1-9]|1[0-2])。
日,最大 31 天,可用 (0[1-9]|[12][0-9]|3[01])。
正则如下:
var regex = /^[0-9]{4}-(0[0-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
console.log(regex.test("2017-06-10")); // true
1.5.4. window操作系统文件路径
要求匹配:
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") ); // tue
console.log( regex.test("F:\\study\\javascript\\regex\\") ); // true
console.log( regex.test("F:\\study\\javascript") ); // true
console.log( regex.test("F:\\") ); // true
其中,在JavaScript 中字符串要表示字符 \ 时,也需要转义。
1.5.5.匹配 id
要求从
<div id="container" class="main"></div>
提取出 id=“container”。
可能最开始想到的正则是:
var regex = /id=".*"/;
var string = '<div id="container" class="main"></div>';
console.log(string.match(regex)[0]);
// id="container" class="main"
因为 . 是通配符,本身就匹配双引号的,而量词 * 又是贪婪的,当遇到 container 后面双引号时,是不会停下来,会继续匹配,直到遇到最后一个双引号为止。
解决之道,可以使用惰性匹配:
var regex = /id=".*?"/
var string = '<div id="container" class="main"></div>';
console.log(string.match(regex)[0]);
// id="container"
当然,这样也会有个问题。效率比较低,因为其匹配原理会涉及到“回溯”这个概念。可以优化如下:
var regex = /id="[^"]*"/
var string = '<div id="container" class="main"></div>';
console.log(string.match(regex)[0]);
// id="container"
边栏推荐
- 【我的创作纪念日】 3周年
- 1.8今日学习
- 微信小程序云开发之券码领取,怎么防止用户领取到相同的数据?
- 1.10今日学习
- 这些JS题面试时一定要答对!
- Chemical reagent Phospholipid-polyethylene glycol-hydroxyl, DSPE-PEG-OH, DSPE-PEG-Hydroxyl, MW: 5000
- npm--package.json---require
- PCL—point cloud data segmentation
- [Mianjing] Mihayou data development on one side and two sides
- 每天填坑,精卫填坑第二集,TX1 配置从固态启动,安装Pytorch
猜你喜欢

npm --package.json---require

Cloud server installation and deployment of Nacos 2.0.4 version

小程序 van-cell 换行能左对齐问题

C语言入门小游戏—三子棋

微信小程序云开发如何将页面生成为pdf?

DSPE-PEG-Silane, DSPE-PEG-SIL, phospholipid-polyethylene glycol-silane modified active group

mysql阶段总结

nucleo stm32 h743 FREERTOS CUBE MX配置小记录

利用 nucleo stm32 f767zi 进行USART+DMA+PWM输入模式 CUBE配置

C语言 0长度数组/柔性数组
随机推荐
meime module
客户评分控件
C语言 0长度数组/柔性数组
Error in render: “TypeError: Cannot read properties of null (reading ‘0‘)“ 报错解决方案
6.27面试集
getattr() function analysis
微信小程序怎么批量生成带参数的小程序码?
5.20今日学习
相对路径和绝对路径
js作用域与闭包
【装机】老毛桃的安装及使用
Cut out web icons through PS 2021
SOCKS5
mysql阶段总结
【我的创作纪念日】 3周年
display,visibility,opacity
简单黑马头条项目
每日面试题 2022/7/28
【手把手带你学nRF52832/nRF52840 · (1)开发环境搭建】
Detailed explanation of the usage of exists in mysql