正则表达式

记录原因

最近使用nodejs比较多,正则表达式对于匹配一个字符来说是比较重要的模块,但是自己本身对正则的概念也是过了一遍,在回头看正则表后就不认识了,所以我记录下正则的使用方法,并记录写经典的例子。

什么是正则

正则表达式是一组由字母和符号组成的特殊文本,它可以用来从文本中找出满足你想要的格式的句子。

1.元字符

元字符 描述
. 句号匹配任意单个字符除了换行符
[ ] 字符种类。匹配方括号内的任意字符。
[^ ] 否定的字符种类。匹配除了方括号里的任意字符
* 匹配>=0个重复的在*号之前的字符。
+ 匹配>=1个重复的+号前的字符。
? 标记?之前的字符为可选.
{n,m} 匹配num个大括号之前的字符或字符集 (n <= num <= m).
(xyz) 字符集,匹配与 xyz 完全相等的字符串.
| 或运算符,匹配符号前或后的字符.
转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ |
^ 从开始行开始匹配.
$ 从末端开始匹配.

1.1 .字符

".ar" => The car parked in the garage.
.字符匹配任何单个字符。

1.2 [ ]字符

"[Tt]he" => The car parked in the garage.
[]方括叫字符集,里面放的参数加上拼的字符作为条件,里面的顺序不影响任何东西,例如,表达式[Tt]he 匹配 the 和 The。

1.3 [^ ]否定字符集

"[^c]ar" => The car parked in the garage.
[^ ]上面的例子,就是除了c意外跟着ar的匹配方式

1.4 重复次数

后面跟着元字符 +,* or ? 的,用来指定匹配子模式的次数。 这些元字符在不同的情况下有着不同的意思。

1.4.1 *号

[a-z]* => The car parked in the garage#21.
例子匹配所有小写的字符,*前的字符出现大于等于0次

1.4.2 +号

"c+t" => The fat cat sat on the mat.
例子,是一个也不能匹配上,因为是+前字符出现大于等于1次,但是这里不能出现两个c,所以匹配不上。

1.4.3 ?号

"[T]?he" => The car is parked in the garage.
例子,匹配到The和he,因为?是指前面的T出现一次或者零次。

1.5 {}号

"[0-9]{2,3}" => The number was 9.9997 but we rounded it off to 10.0.
上面的例子是[0-9]这些能匹配的数字,{2,3}指的是最少两个,最多三个字符的匹配。
在正则表达式中 {} 是一个量词,常用来限定一个或一组字符可以重复出现的次数。

1.6 (...) 特征标群和| 或运算符

"(c|g|p)ar" => The car is parked in the garage.
"(c|g|p)ar"指的是匹配car或gar或par这三个,()更像和数学中的()含义是一样的。
"(T|t)he|car" => The car is parked in the garage.
(T|t)he|car 匹配 (T|t)he 或 car
或运算符就表示或,用作判断条件

1.7 转码特殊字符

"(f|c|m)at.?" => The fat cat sat on the mat.
例子含义匹配fat.或fat或cat.或cat或mat.或mat
用于指定 { } [ ] / + * . $ ^ | ? 这些特殊字符

1.8 锚点

在正则表达式中,想要匹配指定开头或结尾的字符串就要使用到锚点。^ 指定开头,$ 指定结尾。

1.8.1 ^号

"^(T|t)he" => The car is parked in the garage.
^是以The或the开头的数据,所以只能匹配到前面的The(指的是全部文档内容)。

1.8.2 $号

"(at.)$" => The fat cat. sat. on the mat.
和^是相反的$,表示末尾是否能匹配上

2.1 简写字符集

正则表达式提供一些常用的字符集简写。如下:

简写 描述
. 除换行符外的所有字符
w 匹配所有字母数字,等同于 [a-zA-Z0-9_]
W 匹配所有非字母数字,即符号,等同于: [^w]
d 匹配数字: [0-9]
D 匹配非数字: [^d]
s 匹配所有空格字符,等同于: [ f p{Z}]
S 匹配所有非空格字符: [^s]
f 匹配一个换页符
匹配一个换行符
匹配一个回车符
匹配一个制表符
v 匹配一个垂直制表符
p 匹配 CR/LF(等同于 ),用来匹配 DOS 行终止符

3.1 零宽度断言(前后预查)

符号 描述
?= 正先行断言-存在
?! 负先行断言-排除
?<= 正后发断言-存在
?<! 负后发断言-排除

先行断言和后发断言都属于非捕获簇(不捕获文本 ,也不针对组合计进行计数)。 先行断言用于判断所匹配的格式是否在另一个确定的格式之前,匹配结果不包含该确定格式(仅作为约束)。
用人话说就是排除使用判断的内容,匹配剩余的内容,上面表格内容里的前后指的针对的字符串。
例子:(?<=$)[0-9.]* =>$0,1,2,3,4,5,6,7,8,9,.

3.1.1 ?=... 正先行断言

?=... 正先行断言,表示第一部分表达式之后必须跟着 ?=...定义的表达式。
"(T|t)he(?=sfat)" => The fat cat sat on the mat.
匹配到The。
理解方式:匹配这个正先断言前的内容,包含不匹配断言。

3.1.2 ?!... 负先行断言

"(T|t)he(?!sfat)" => The fat cat sat on the mat.
表达式 (T|t)he(?!sfat) 匹配 The 和 the,且其后不跟着 (空格)fat。
理解方式:和正先断言相反,不匹配断言前的内容包含不匹配断言。

3.1.2 ?<= ... 正后发断言

"(?<=(T|t)hes)(fat|mat)" => The fat cat sat on the mat.
表达式指的是the 或the 后跟fat或mat

3.1.2 ?<= ... 负后发断言

"(?<!(T|t)hes)(cat)" => The cat sat on cat.
cat前跟的不是the 和The

4.1 标志

标志也叫模式修正符,因为它可以用来修改表达式的搜索结果。 这些标志可以任意的组合使用,它也是整个正则表达式的一部分。

标志 描述
i 忽略大小写。
g 全局搜索。
m 多行修饰符:锚点元字符 ^ $ 工作范围在每行的起始。

4.1.1 忽略大小写 (Case Insensitive)

"/The/gi" => The fat cat sat on the mat.

"/.(at)/g" => The fat cat sat on the mat.

4.1.3 多行修饰符 (Multiline)

"/.at(.)?$/" => The fat
cat sat
on the mat.
"/.at(.)?$/gm" => The fat
cat sat
on the mat.
这个m会匹配每一行的结尾

5.1 贪婪匹配与惰性匹配 (Greedy vs lazy matching)

正则表达式默认采用贪婪匹配模式,在该模式下意味着会匹配尽可能长的子串。我们可以使用 ? 将贪婪匹配模式转化为惰性匹配模式。
"/(.at)/" => The fat cat sat on the mat.
"/(.
?at)/" => The fat cat sat on the mat.

6.1 常见的正则分析

6.1.1、数字、26个英文字母或者下划线组成的字符串:^w+$
分析:^表示开头,w是字母数字缩写,+表示大于1个,$表示结束
6.1.2、中文字符的正则表达式:[u4e00-u9fa5]
6.1.3、^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])d{8}$
分析:^(13是13开头,[0-9]零到九,14[5|7]:14开头,5或7,15[0|1|2|3|5|6|7|8|9],18[0|1|2|3|5|6|7|8|9]和前面一样,d{8}匹配数字,至少8位
6.1.4、身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(d{15}$)|(d{18}$)|(^d{17}(d|X|x)$)
分析:d{15}$是最少15数字,|(d{18}$)或者18位数字,(^d{17}(d|X|x)$)或者17位数字加上大小x
6.1.5、Email地址:^w+([-+.]w+)@w+([-.]w+).w+([-.]w+)$
分析:^w+是开头随机数大于一个,([-+.]w+)
多个-或随机一个加上数字多个,这个组个是大于零的,@w+([-.]w+)是@加上数子-或者任何数在机上数字,.w+([-.]w+)$是和前那一样
6.1.6、日期格式:^d{4}-d{1,2}-d{1,2}
6.1.7、匹配括号外所有的逗号,理解了好久
,+(?=[^)]*((|$))
匹配方式是逗号有大于等于一个,贪婪正向断言,除去,),但是有*所以匹配一个多个,,所有的逗号都能匹配上,加上后面的(|$之前的贪婪匹配方式,就可以获取到所有括号外的逗号。
6.1.8、获取文件名称:

let csvFileName = fileName.match(new RegExp('(?<=(?!.*/)).*(?=(.csv)$)', 'g'));

这里是全局匹配,以.csv为结束,加上正先断言,中间使用.*匹配所有字符,这个前面是?!负先断言,而且是非贪婪匹配所以加上/就匹配到最后那个/
之后,我发现能简写成

let csvFileName = fileName.match(new RegExp('(?!.*/).*(?=(.csv)$)', 'g'));

感谢

原文地址:https://www.cnblogs.com/liuyang95/p/14165799.html