前言:提起正则,做深度学习的朋友可能会首先想到防止参数过拟合的 L1/L2 正则算法。此正则非彼正则。 正则表达式(Regular Expression, regex) 用于字符串匹配,规则明确、语法精简、应用场景极其广泛。几乎所有写代码的朋友都或多或少接触过一点 regex ,但你真的会用吗?比如,用于全匹配
aabc
的 regex 为^(?.)\k(?!\k)(?.)(?!\k(b)|\k).$
,你可以给出解释吗?今天,不妨一起回顾一下 regex 中的知识;此外,笔者将分享一些拓展内容,比如 vim 中的 magic 、练习 regex 的绝佳在线工具等。
入门笔记速查
本段及下段内容是 B站UP主free-coder 视频正则表达式-从入门到group入门的笔记。阅读原文可以观看其视频。 强烈安利这位技术UP。
基础内容
对于字符串abc
,我们输入正则表达式:
abc
,可以匹配到出现在任意位置的abc
^abc$
, 全匹配 ,^a
表示这个字符串开头必须是a
,c$
表示这个字符串结尾必须是c
此外,我们可以用 中括号 []
某个范围的匹配,比如:
[a-z]
表示匹配任意位置的某个字符,这个字符的范围是a,b,c,...,z
[a-zA-Z]
表示匹配任意位置的某个字符,这个字符的范围是a,b,c,...,z,A,B,C,...,Z
而在中括号[]
内,^
表示取反,如,^[^a-z]$
表示: 全匹配一个字符,这个字符不属于a,b,c,...,z
而 大括号 表示字符的数量,如:
^[a-zA-Z]{3}$
表示,全匹配一个字符串,这个字符串有3
个字符,每个字符都属于a,b,c,...,z,A,B,C,...,Z
^[a-zA-Z]{3,}$
表示,全匹配一个字符串,这个字符串 至少 有3
个字符,每个字符都属于a,b,c,...,z,A,B,C,...,Z
^[a-zA-Z]{3,6}$
表示,全匹配一个字符串,这个字符串 至少 有3
个字符, 至多 有6
个字符,每个字符都属于a,b,c,...,z,A,B,C,...,Z
其他符号
如.
表示除了 回车 的任意符号, 除了 回车/换行符号 line terminators 。
而 \d
与 [0-9]
同, \D
与 [^0-9]
同。我们一般用 [\d\D]
表示任意字符, 包括 回车/换行符号 line terminators 。
![符号 [dD] 匹配到一个字符串,不会受换行影响](https://gitee.com/piperliu/pi...
\w
是常用互联网命名符号,与 [a-zA-Z0-9_]
同。
s 是特殊符号,与 [\r\n\t\f\v ]
同,\S
是非特殊符号 [^\r\n\t\f\v ]
。
此外,还有表示数量的符号:
w?
同{0,1}
w*
同{0,}
w+
同{1,}
举例:匹配 qq 邮箱
以我的邮箱 [email protected]
为例:
^[a-zA-Z0-9]\w*
第一个字符不能是下划线- 后面是
@qq\.com$
,其中,\.
表示字符“.
”,\
是转义符号。
用 JavaScript 匹配:
'[email protected]'.match(/^[a-zA-Z0-9]\w*@qq\.com$/)
其中,字符串对象的match()
函数中用//
包裹正则表达式。
进阶:组属性
组属性很神奇,有了组属性,我们可以表达更复杂的语法规则。
组基础
我们用括号()
定义哪些部分是一个组。
'[email protected]'.match(/^([a-zA-Z0-9]\w*)@qq\.com$/)
其中,我们将piperliu
即([a-zA-Z0-9]\w*)
定义为一个组,且是第1个组。
如上,在 JavaScript 对象的组对象 groups 中,并没有我们刚刚定义的组。这是因为 groups 中只存放定义了名称的组。我们用 ?
定义组的名称。
'[email protected]'.match(/^(?[a-zA-Z0-9]\w*)@qq\.com$/)
如上,我们定义组名称为first
。
组实现引用
在同一个正则表达式中,我们可以直接用索引引用组(\1
),也可以用名字引用定义了组名的组(\k
)。
组的索引是从 1 开始的,而非 0 , 因为\0
已经被用来表示asc码的第一个码。
对于字符串1212
,我们可以用如下的方式匹配:
^\d\d\d\d$
^(\d\d)\1$
,引用第一组^?
,直接用了组名(\d\d)\k $
组的特殊结构
有了组,我们可以实现很多 Group Construction ,首先以 Positive Lookahead 为例。
对于字符串foobar,fooboo
为例,我们想找出foo
,且这个foo
必须紧紧靠在bar
前,则可表达如下:
foo(?=bar)
再举个例子, Positive Lookbehind 和 Negative Lookbehind ,对于字符串barfoo,boofoo
,我们想找出foo
:
- 这个
foo
必须紧紧靠在bar
后,则(?<=bar)foo
- 这个
foo
前紧邻的必须不是bar
,则(?!=bar)foo
老师例题
现在想匹配字符串形式aabc
,要注意不可以匹配到:
aaaa
aabb
aaba
则正则表达式如下:
^(?.)\k(?!\k)(?.)(?!\k|\k).$
分析一下:
^(?.)
第一个字符,定义为组a
,可以是任何字符.
\k
第二个字符要与第一个字符同(?!\k)
此外,第二个字符紧后面的字符,不可以是组a
的字符(?.)
第三个字符定义为组b
(?!\k|\k)
此外,第二个字符紧后面的字符,不可以是组b
或组a
的字符.
第四个字符任意
vim magic
在上古神器 vim 中,我习惯 使用类似正则的思想,进行批量注释 (其实是 VS Code 中 vim 插件,块快捷键 Ctrl+v 与粘贴键有冲突),如下图(编辑模式下:2,3s/^/#/g
)。
而对于 vim 来讲,在使用 /
正则查找时,分为两个模式:
- magic 模式
- nomagic 模式
对于 magic 模式,我们的特殊符号如 .
就是特殊含义(任何字符),即正常的正则表达模式;对于 nomagic 模式,我们的符号都只表达符号本身,使用特殊含义需要用 \
转义。
更多内容,如 vim 中的 very magic 等,可以参阅:
https://www.cnblogs.com/pense...
学习资源
https://regex101.com/
Online regex tester and debugger: PHP, PCRE, Python, Golang and JavaScript
如其英文名,极其可靠的在线正则表达式调试工具,汇集了功能包括: 教学、查阅、解析与分析、运算、知识检测等。
阅读原文:https://www.bilibili.com/vide...
感谢你读到最后!我是小拍,一名计算机技术爱好者!觉得文章不错的话,可以点击“在看”支持我一下!有任何批评建议或者合作事宜,可以给我发邮件 [email protected] ,或者关注公众
Piper蛋窝
,回复「微信」来加我微信联系~