这两天又看了一下正则表达式的入门手册,有些原来没有注意到的东西,记录一下。
匹配类型
有些元字符只匹配位置
- \b
- ^
- $
有些元字符只匹配数量
- *
- +
- ?
[]中是用来放匹配的字符的,所以匹配位置的东西在里面是无效的
比如我想匹配0:忙,1:闲
中的枚举,如果我用下面的正则是无法匹配的:
([\dH]+):(.*?)[,;$]
因为$
在[]
中表示的是字符而不是位置. 正确的写法是:
([\dH]+):(.*?)([,;]|$)
.*?
的解释
.
匹配任意字符,*
匹配任意数量,?
使用懒惰模式
后向引用
例:\b(\w+)\b\s+\1\b
匹配重复的单词,像go go, 或者kitty kitty
零宽断言
断言的目的是使用字符串匹配位置但不匹配任何字符串,即被断言匹配的字符串仍然可以继续被匹配。另一种角度来说,可以用来判断字符串中是否包含某字符串(因为不会匹配任何字符串)。
- (?=exp) 零宽度正预测先行断言
- (?<=exp) 零宽度正回顾后发断言
- (?!exp) 零宽度负预测先行断言
- (?<!exp) 零宽度负回顾后发断言
例:\b\w*q(?!u)\w*\b
匹配包含后面不是字母u的字母q的单词
理解:正与负其实是==和!=的意思;先和后其实是匹配所在位置右边和左边的意思(因为这个写在正则表达式中间分不清是与前面的东西配合还是与后面的东西配合)。
例:
- 匹配后面为_path,结果为product
'product_path'.scan
/(product)(?=_path)/
(?<=exp):零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp - 匹配前面为name:,结果为wangfei
'name:wangfei'.scan
/(?<=name:)(wangfei)/
(?!exp):零宽度负预测先行断言,断言此位置的后面不能匹配表达式exp。 - 匹配后面不是_path
'product_path'.scan
/(product)(?!_path)/ - 匹配后面不是_url
'product_path'.scan
/(product)(?!_url)/
(?<!exp):零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp - 匹配前面不是name:
'name:angelica'.scan
/(?<!name:)(angelica)/ - 匹配前面不是nick_name:
'name:angelica'.scan
/(?<!nick_name:)(angelica)/
多行模式和单行模式并不是反义词
- 多行模式:
^
和$
分别匹配任意一行的行首和行尾 - 单行模式:
.
也匹配换行符\n
体会
- 之前一直用
{1,}
来表示重复1次及以上,其实用+
就可以 - 要搞明白使用正则表达式的库的函数都是干什么用的,下篇就写这个吧
常用正则表达式
- IP:
(([1‐9]?\d|1\d{2}|2[0‐4]\d|25[0‐5]).){3}([1‐9]?\d|1\d{2}|2[0‐4]\d|25[0‐5])
- IP:
((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
- Email地址:
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
- 域名:
[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
- 手机号码:
^(13[0-9]|14[0-9]|15[0-9]|166|17[0-9]|18[0-9]|19[8|9])\d{8}$
- 强密码(包含大小写、数字,无特殊字符,长度8-10):
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
(断言) - 日期格式:
^\d{4}-\d{1,2}-\d{1,2}
- 中文字符:
[\u4e00-\u9fa5]
- 空白行:
\n\s*\r
(^\s*\n
)
还没搞明白的特殊匹配方法
平衡组/递归匹配