- Published on
正则表达式速记口诀
- Authors

- Name
- 林晓东
- @xiaodong5959
这是一个正则的助记口诀/顺口溜,让我们用30分钟时间来轻松背下难记的正则
欢迎通过issue提交更好的口诀或者补充未提到的正则表达式
首先先奉上口诀:
从前有个傻大三,
哇塞,日子过得特别难
\w\s\r\z\d\t\b\n
人傻人穷只有捡破烂
做梦都想变成大富豪,就不用再出来捡破烂
\W\S\D\B
每天哼着歌儿出去捡破烂
两手叉着腰,左手捡了右手又捡
a|b
你问他捡到钱没
?
左手回答得还行,右手被问得头冒金星
+*
只有装进袋子把数字标
{n}
关上门来把金银财宝往屋里搬
[abc]
脑袋儿被门夹了不知道啥东西要选
[^abc]
钢镚儿一碗,铁镚儿一碗
(abc)
没问题的打个标记,好知道有好多钱
(?<name>)
有问题的放一边,挤破脑袋也还要向前再看一眼
(?=exp)(?!exp)(?<=)(?<!)
剩下的铜钱儿用线串
[a-zA-Z0-9]
一不小心遇到地头蛇,一顿拷问被吓得赶紧溜回家
+?*?
释义
嘴巴儿尖尖,句句都是钱
尖尖代表^符号,钱代表$符号
傻大三这个人一张嘴说话,句句都是以钱收尾
所以我们get到了
| 正则表达式 | 描述 | 示例 |
|---|---|---|
^ | 匹配字符串的开始 | ^acb 匹配以abc开头的字符串 |
$ | 匹配字符串结尾 | abc$匹配以abc结尾的字符串 |
哇塞,日子过得特别难.
在正则里面有许多的元字符,这里收集了比较常用的一些,取元字符的来当声母,用来助记这些元字符,当然,我们更明白元字符所对应的英文单词,就无须死背元字符所对应的的内容了.
所以我们get到了一大串的元字符
| 代码 | 描述 | 对应文字 | 对应单词 |
|---|---|---|---|
\w | 匹配一个单词的组成部分,字符,数字,下划线.(是否匹配中文视操作系统和应用环境而定) | 哇 | Word |
\s | 匹配空白符 | 塞 | Space |
\r | 回车 | 日 | Enter |
\z | 字符串结尾(类似$,但不受处理多行选项的影响) | 子 | ? |
| 过 | 过 | ||
\d | 数字 | 得 | Digital |
\t | tab制表符 | 特 | Tabulator key |
\b | 边界,单词分界位置 | 别 | Boundary |
\n | 换行符 | 难 | Line feed |
. | 点号(相当于句号),在一个段落中,以它结尾,它包括了前的各种符号,但不匹配换行符.因为换行就是新段落了 | . |
做梦都想变成大富豪,就不用再出来捡破烂
变成大富豪,表示元字符变成了大写字母
就不用再出来破烂,表示不再匹配,相当于对以上小写的元字符取反
所以我们get到了
| 代码 | 描述 |
|---|---|
\W | 匹配一个非单词的组成部分,字符,数字,下划线.(是否匹配中文视操作系统和应用环境而定) |
\S | 匹配非空白符 |
\D | 非数字 |
\B | 非边界,单词分界位置 |
两手叉着腰,左手捡了右手又捡
这一表示正则里面的分枝匹配,形如a|b表示两边或的匹配关系,即可以匹配a也可以匹配b
傻大三捡垃圾,左边有就左手捡到,右边有,就右手捡起来.
你问他捡到钱没?左手回答得还行,右手被问得头冒金星,只有装进袋子把数字标
问到捡到钱没,这是一个问句,回答应该是是与否,代表0或者1,所以有正则?匹配0次或者1次
因为他左手刚刚捡到了一块垃圾,所以他傻傻地也知道左手捡到有东西,在数学里面就是用正号+表示,至少有一个.
被问得头冒金星,他也不知道右手到底有没有捡到有东西了.金星用*表示,可能没有捡到有,也可能捡到很多
只好数一下装进袋子里面,用数字标上有多少.袋子用{}表示,数字用n表示有多少个.得到完整的正则表达式{n}即表示前面的匹配n次
于是我们get到的正则的匹配模式
| 代码 | 描述 |
|---|---|
+ | 匹配至少一次 |
* | 匹配0次或者多次 |
? | 匹配零次或者一次 |
{n} | 匹配n次 |
{n,m} | 匹配n到m次 |
{n,} | 匹配n次或者更多次,没有m代表无穷尽 |
关上门来把金银财宝往屋里搬,脑袋儿被门夹了不知道啥东西要选
关上门表示[]符号,关在里面的金银财宝,都可以往屋里搬,所以表达式[abc]表示匹配abc任意一个.
结果傻大三的头^不小心被门给夹住了,不知道要这些金银财宝了.所以表达式[^abc]表示匹配不是abc这些字符的.
钢镚儿一碗,铁镚儿一碗
碗用()表示,傻大三还是知道对这些垃圾进行分类,也就是正则里面的分组,分组之后,不仅可以用于前面的匹配模式,也可以用于后面的反向引用和零宽匹配及更多的功能.
比如(abc){2}表示匹配连续的两个abc即abcabc
没问题的打个标记,好知道有好多钱
傻大三对碗打个标记,以免有疑问?时才好知道有好多钱,所以有正则表达式形式(?<name>exp),打好标记之后,在后续就可以通过这个标记来识别引用了.
比如\b(?<Word>\w+)\b\s+\k<Word>\b表示匹配连续重复的单词,比如go go.如果不打标记,默认使用数字来识别,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。所以这个表达式不打标记的写法就是\b(\w+)\b\s+\1\b
有问题的放一边,挤破脑袋也还要向前再看一眼
有问题?的,有可能是真钢镚,即等号=表示,有可能不是真钢镚,即非!表示
放一边,表示只匹配了,但不参与捕获.和前面的^,$,\b一样,是属于零宽断言,它们 本身不匹配任何字符,只是对 "字符串的两头" 或者 "字符之间的缝隙" 附加了一个条件.
于是有正预测先行断言(?=exp),表示断言自身出现的位置后面能匹配表达式,比如\b\w+(?=ed\b)表示匹配以ed结尾的单词,但不包含ed;
同理有负预测先行断言(?!exp),和上面的意思相反,即不能满足表达式.比如\b\w*e(?!d)\w*\b表示匹配包含e的单词,但同时e后面不能跟着字符d.它和\b\w*e[^d]\w*\b的区别是,后者的[^d]会参与一次匹配,比如它会匹配上e,abc,因为里面的,参与了[^d]的匹配.
挤破脑袋向前<,前面说的是先行断言,即先匹配上前面的表达式.相反的,挤破脑袋往前面去就变成了后发断言.即有
正预测后发断言(?<=exp)表示断言自身出现的位置前端能匹配表达式exp
负预测后发断言(?<!exp)表示断言自身出现的位置前面不匹配表达式exp
零宽断言是先满足匹配其自身表达式后,再获取断言里面的表达式是否满足. 比如(?<=\d{4})\d+(?=\d{4})去匹配1234567890,先匹配上\d+,再判断(?<=\d{4}和(?=d{4}),于是最终的匹配结果是56.
综合以上三条,我们对于正则分组,可以再总结一下
| 代码 | 描述 |
|---|---|
(exp) | 分组匹配,后续可以通过\n进行反向引用 |
(?<word>exp) | 分组匹配命名,后续可以通过\k<word>进行反向引用 |
(?:exp) | 只分组,不生成分组编号,也不捕获.相当于只看一眼:而已 |
(?=exp) | 匹配exp前面的位置 |
(?!exp) | 匹配后面不是跟的exp的位置 |
(?<=exp) | 匹配exp后面的后面 |
(?<!exp) | 匹配前面不是跟的exp的位置 |
剩下的铜钱儿用线串
用线-串,表示把铜钱儿都串起来了,就是正则里面的[a-zA-Z0-9]这种表示方法,表示a到z的全部大小写字母和0到9的全部数字.
一顿拷问被吓得赶紧溜回家
遇到地头蛇拷问?,溜回家不再捡垃圾,就是正则里面的遇到?由默认的贪婪匹配变成了非贪婪(惰性)匹配.
比如对于字符串aabaab用正则a.*b会匹配上整个字符串,因为它是贪婪匹配的,里面的.*会尽可能长的进行匹配.
而a.*?b则只会匹配aab.因为对于.*遇到了?号,就被变成了非贪婪匹配了.
于是结合前面的匹配模式,我们可以get到
| 代码 | 描述 |
|---|---|
+? | 匹配至少一次,但尽可能少地匹配 |
*? | 匹配0次或者多次,但尽可能少地匹配 |
?? | 匹配零次或者一次,但尽可能少地匹配 |
{n,m}? | 匹配n到m次,但尽可能少地匹配 |
{n,}? | 匹配n次或者更多次,没有m代表无穷尽,但尽可能少地匹配 |