简介

正则表达式就是用一个字符串来描述特征,去匹配另一个字符串是否符合这个特征。正常的搜索只能去匹配一个特征,而正则可以匹配多个特征。比如我想找到日志文件中2020年3月9日的post请求(这是两个特征)。如下图

1

概念

正则表达式基本可以分为两个部分,一个部分来描述你要匹配字符串的范围(后面用范围简写),另一个是你要匹配的数量(后面用数量简写)。那么要怎么去表示呢,范围用中括号里面的字符来表示范围,数量用大括号里面的来表示数量。

比如我想在收到的短信(如下)里找到六位的短信验证码,他有两个特征纯数字长度是六位

【爱奇艺】您的验证码是684029,转发给他人可能导致账号被盗,请勿泄漏,谨防被骗。
【腾讯科技】382525(登录保护验证码),用于QQ28*******9登录的设备验证,请勿转发。如不想接收此类短信,请回复T退订
【百度帐号】您在百度请求的验证码是:376404

纯数字我可以用 [0123456789] 来表示,长度是六位我可以用 {6,6} 来表示,大括号里的第一个6是最少匹配的数量,第二个6是最多匹配的数量。如下图

1

反向匹配

比如我想匹配数字以外的所有字符该怎么写,我们可以在中括号里的开头加^就可以反向匹配了,如 [^0123456789] ,因为不是数字的字符不止6个,它最少一个最多无数所以我们这么写 {1,} 。组合起来就是[^0123456789]{1,},如下图

1

元字符

但是这样写是有一个问题的,纯数字好说才10位,要是字母加数字加字符,或者说Unicode全部字符还这样写显然是不可能的,所以正则表达式还给我们提供了一些元字符来提供我们使用。我这里给出一些常用的如下

范围元字符

w          单词或数字,这里的"单词"字符使用Unicode字符集(就是说包括汉字)
\W          非单词或数字的任何字符
\d          数字                              等价于[0-9] [0123456789]
\D          非数字的任何字符                    等价于[^0-9]
\s          任何不可见字符。                    等价于[ \f\n\r\t\v]
\S          任何可见的字符。                    等价于[^ \f\n\r\t\v]
.           任意字符, 但不包括 \r 和 \n

数量元字符

*           任意数量个字符(包括0个)           等价于匹配长度     {0,}
+           至少一个字符                      等价于匹配长度     {1,}
?           0字符或者1字符                    等价于匹配长度     {0,1}

{n}         n 个字符
{n,}        最少 n 个字符
{,m}        最多 m 个字符
{n, m}      最少 n 个字符, 最多 m 个字符

我们在使用元字符匹配验证码试试[\d]{6,6}

1

再次反向匹配 [\D]+ [^\d]+

1

其他元字符

定位元字符

定位符使您能够将正则表达式固定到行首或行尾,或者是在单词的开头或结尾,或者是直接搜索某个单词。

^           表示行的开头
$           表示行的结束

\b          单词边界
\B          非单词边界
^$ 元字符

如果你需要匹配字符串的某一行,可能就需要用到 ^$元字符了,这里的 ^ 和反向匹配的 ^ 不是一个概念。需要注意的一点是有没有设置Multiline属性,这个属性会开启多行匹配,这是匹配的就不是某一行是整个字符串。

没有设置Multiline属性的 ^.*$

1

设置Multiline属性的 ^.*$

1

\b 元字符

单词边界符是用空格和换行符(\r\n)来划分单词边界的,\b 放的位置效果也会不同。

演示字符,python 禅

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

\b 放在头部 ,搜索en开头的单词\ben

1

\b 放在尾部 ,搜索en结尾的单词en\b

1

\B 元字符

\B就是非边界符,他也和放的位置有所不同,只有两边都写\B才能匹配到单词中间的字符。如下图

1

组和运算符

image-20200319134822138

  • 逻辑运算符

    正则表达式只有一个逻辑运算符,| 逻辑或运算符(或的意思 or)

  • 用小括号来划分区域,每个小括号中的部分是不同的组

这两个基本是放在一起用的,比如我想同时匹配moodfood,我就可以这么写 (m|f)ood

1

贪婪模式

正则表达式默认是贪婪模式,贪婪模式会尽可能多的去匹配(匹配的字符越多越好),非贪婪模式则是尽可能少的匹配(匹配到了我就不继续往后找了)。非贪婪模式只要在数量后面加一个?就代表非贪婪模式。如果我们不去用 \b 去找以b开头的单词,贪婪模式 b.* ,非贪婪模式 b.*?记得有前后是有空格的

非贪婪模式

1

贪婪模式

1

修饰符

python的修饰符(flag标识)

re.I            使匹配对大小写不敏感
re.L            做本地化识别(locale-aware)匹配
re.M            多行匹配,影响 ^ 和 $
re.S            使 . 匹配包括换行在内的所有字符
re.U            根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B,pyton默认是这个模式
re.A            根据ASCII字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X            该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

正则支持语法情况

image-20200319141010986

练习题

答案不是唯一,也不一定正确

1、匹配电话号码

p = re.compile(r'\d{3}-\d{6}') 
print(p.findall('010-628888'))

2、匹配IP

re.search(r"(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]\.)","192.168.1.1")

3、匹配空行

n\s*\r

4、匹配邮箱

^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$

5、匹配验证码(纯数字的)

d{4,6}(?!\d)

6、匹配身份证号

^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$

7、匹配url

[a-zA-z]+://[^\s]*

8、匹配MAC地址

^([0-9a-fA-F]{2})(([0-9a-fA-F]{2}){5})$ 

9、匹配汉字

[\u4e00-\u9fa5]

10、匹配QQ号

[1-9][0-9]{4,}

11、匹配base64

[a-Z0-9/+=]*

12、安恒waf防 (shiro <= 1.2.4 和 shiro => 1.2.4)(安恒的WAF所有特殊字符都要转移很奇怪)

匹配rememberm后面长度超过100的base64字符和空格等号

(?i:rememberm)[a-zA-Z0-9\/\+\=\ ]{100,};?

# 正常写法
(?i:rememberm)[a-zA-Z0-9/+= ]{100,};?
0
最后修改日期:2020年6月1日

留言

神王nb

0

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。