Reference 正则表达式30分钟入门教程
废话:
第一次看这篇经典入门,还没到一半就放弃了。这次终于看到了三分之二才放弃!虽然每次学习之后感觉自己都没有懂,但是这次终于惊喜地发现在没有懂的过程中,懂了一点点。因为正则,真的是前端路上迈不过去的一道深深的坎啊!每次写代码都要悔恨为什么不懂正则!为什么!
这篇文章是对30分钟入门教程的个人理解,如果您已读懂该教程,请忽略这篇文章
1. 正则到底是什么鬼
使用命令行操作、或者数据库操作,你肯定使用过 * 这个操作符,我们经常用它来匹配全部,正则就像是对这个操作符的延伸。比如说我在使用git提交文件,我一般会git add *
, 但是如果我不想添加全部,想要添加以select开头的文件呢,这个逻辑就可以用正则来表示。 (这只是一个假想,不要当真)
2. 最简单的正则表达式
/hi/ #用来匹配hi
正则表达式在分析字符串的时候,通常会把字符串拆分成一个一个的单词,并且连单词的缝隙也不放过,这点稍后解释。
所以/hi/ = h + i ,这个正则就是用来匹配字符串中包含h,后面紧跟着一个i的字符串,你可以在浏览器里测试
/hi/.test('hi') # true
/hi/.test('hhhhiiii') # true
/hi/gi.test('hhhHIiii') # true
gi表示一种匹配模式,使用g则进行全局的匹配,使用i会忽略大小写
\b 单词的缝隙
如果你想要精确匹配hi这个单词,在hhhiiiii这种应该返回false,要如何做呢?
/\bhi\b/.test('hi')
想象每个英文单词的缝隙都隐藏着一个\b
welcome to beijing
\bwelcome\b \bto\b \bbeijing\b
虽然说单词之间是由空格、逗号之类的分隔符隔开的,但是呢,空格也是一个字符,它属于字符串的一部分,\b却是一个隐形字符,可以帮助你悄无声息地判断出一个是否是一个完整单词,而不用消耗你的字符串元素。大家叫他元字符,metacharacter
. 点(除了换行符以外的任意字符)
.也是一个元字符。
Q: 匹配hi后面不远处跟着一个Lucy
-> 翻译:hi + 中间有很多不明的字 + Lucy
\bhi\b.*\blucy\b
一个.只能匹配一个字符,多个点就用.*来表示。
* 也是一个元字符,但是它表示的是数量,.*可以理解为,点这个模式被乘以了n次,这个n是多少呢?
- *表示任意数,毕竟*是个通配符嘛
- +表示 >= 1
- {6} 就是精确的6次
- {6, 12} 6~12次之间
- {6, } >=6次
- ?出现1次或不出现
所以你可以这样使用
.*
.+
.{6}
.{6,12}
.{6,}
.可以替换成其他的元字符,可能你常常看到他们:
\d 表示一位数字0, 1, 2,…9
举例: 0\d{2}-\d{8}, 意思就是,这个字符串以0开头,然后跟着一个2个数字,跟着连字符-,跟着8位数字
\s 任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等
- \w 匹配字母或数字或下划线或汉字等
- [afe] 如果你想要匹配自己定义的一个集合,可以使用[ ],表示a或f或e中的一个字符,注意这也是一个单字符匹配,或者符号集[.?!]。同时也可以指定一个范围[a-z] [A-Z] [0-9], 此时的[0-9]等同于\d, [a-zA-Z0-9_]等同于\w
表示字符 | 表示数量 |
---|---|
. | * |
\d | ? |
\s | + |
\w | {n},{n,m},{n,} |
[aeiou] |
反义
大写是小写的反义
字符 | 含义 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
<a[^>]+> 匹配<a开始,非>结束的内容,其实是<a..任意内容..>
^ $
^ 表示字符串的开始,$表示字符串的结束。开始时^的取反功能和开始标志让我有点捉摸不清。不过/^asjfhkajsdfhjkshf\$/
这两个元素通常就被安置在开始和结束的位置,如果你不明所以,只要在开头看到^,或者在结尾看到$,只要明白这是开始和结束即可。
为什么要加这两个标志呢,因为匹配可能发生在中部尾部头部,所以如果你想要从头到尾去规定一个字符串就要加上这个限制条件,比如你规定一个长度只能为6的字符串,你就需要加上头尾,否则它匹配一个8个长度的字符串,中间确实有6个字符,也会返回true
举例:
/.{6}/.test('123456789'); #true
/^.{6}$/.test('123456789'); # false
字符转义
匹配. * \ 这些特殊字符,加上\进行转义:., *, \
例子分析
\(?0\d{2}[) -]?\d{8}
( 转义,?一个括号出现1次或不出现,然后跟着0,然后2个数字,然后)或者-,)-出现一次或0次,然后8个数字
解析的时候要把 字符和字符的数量 放在一起考量。
(0nn)12345678
0nn-12345678
0nn12345678
分枝条件 -
分枝就像路分成了两条,但哪个都能到达目的。类似于 || ,
注意顺序,原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。其实和js的 ||一样呢
\d{5}|\d{5}-\d{4} 与 \d{5}-\d{4}|\d{5} 结果不同
分组
用小括号圈起来成为一个子表达式。唯一一个不用看就理解的信息
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
分析:
23n或252或0nn或0n. 重复3次,23n或252或0nn
最后一个没有点,所以单独拎出来,重复三次的小组,规定了一个合规的ip数字,后面跟着点。
后向引用(? )
\b(\w+)\b\s+\1\b
解释:匹配重复的单词。\b(\w+)\b 表示一个单词,s+许多空格,\1表示\b(\w+)\b匹配的单词,它会被自动捕获到\1中。分组匹配时,匹配的结果会按顺序储存在\2 \3 \4..
\b(?<Word>\w+)\b\s+\k<Word>\b
如果你觉得\1实在太不友好,此处的<Word>就是你重命名\1的方式。<Word>指代,\k<Word>表示反向引用。(在js测试时这个语句报错,不明白==)
分类 | 代码/语法 | 说明 |
---|---|---|
捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 |
(?exp) | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp) | |
(?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 | |
零宽断言 | (?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 | |
(?!exp) | 匹配后面跟的不是exp的位置 | |
(? | 匹配前面不是exp的位置 | |
注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
Q: 捕获是什么意思?
https://www.cnblogs.com/yakun/p/3795589.html