本文初步介绍 正则表达式的定义,分类的组成部分。并举例编码
答:在unix系统中,用来表示规则的字符串。在开发语言中需要处理大量的字符串,引入了这个规则。
字符串的处理:
1. 过滤字符串,在字符串中获取需要的部分
2. 验证字符的输入是否符合规范, 例如用户名,密码的验证
3. 切割字符串, 划分字符内容
4. 替换字符串, 替换文本内容的信息。
目前产雇佣的两大正则系统: POSIX系统, Pcre系统。
开发语言 Perl --> Pcre
C --> POSIX
PHP --> POSIX, Pcre
Python --> Pcre
可以划分为三个部分,原子,元字符和模式修正符。
原子:是正则表达式的最小单元。所有的字符都是原子。 包括可见字符: 1-9,a-z,&*等。
不可见字符: \n, \r , \v , \t, \f等
元字符: 原子修饰符。 修饰原子。 可以划分为, 整体修饰,数量修饰,位置修饰和特殊修饰(转义,词边界等)。
模式修正符: 对正则表达式进行一些额外的匹配规则 。
原子:正则表达式的最小单元。所有的字符都是原子。 包括可见字符: 1-9,a-z,&*等。
不可见字符: \n, \r , \v , \t, \f等。
需要学习的是有 7个专用的转义字符:
\d: 表示数字 0-9 |
\D: 表示除了 数字 0-9 以外的字符 |
\s :表示任意空白字符(不可见,例如空格,换行。 \n,\r) |
\S: 表示除了空白字符以外的 任意字符 |
\w: 表示a-z,0-9,A-Z,_ 。 即常用的变量名元素 |
\W:表示除了 [a-z0-9A-Z_] 以外的任意字符 |
. : 表示除了\n以 的任意字符 |
import re # 导入 re模块
#### 正则表达式的应用测试步骤
# 1. 定义 正则表达式
# 2. 定义 检查字符
# 3. 检查
# 定义表达式的调用 函数
# 方便后续的测试
def run(pattern:str,str1:str):
res = re.search(pattern,str1)
print(type(res), res)
#####################################
pattern1 = 'a'
str1 = '13afas'
res = re.search(pattern1,str1)
print(type(res), res) #
pattern2 = '\d' # 0-9 纯数字
str ='abc,123'
res = re.search(pattern2,str)
print(type(res), res) #
pattern2 = '\D' # 除了0-9 以外的任意字符
str ='abc,123'
res = re.search(pattern2,str)
print(type(res), res) #
pattern2 = '\D' # 除了0-9 以外的任意字符
str ='=bc,123'
res = re.search(pattern2,str)
print(type(res), res) #
pattern2 = '\w' # 0-9,a-z,A-Z,_ . 即我们常用的变量命名元素
str ='=bc,123'
run(pattern2,str) #
pattern2 = '\w' # 0-9,a-z,A-Z,_ . 即我们常用的变量命名元素
str ='_bc,123'
run(pattern2,str) #
pattern2 = '\W' # 除0-9,a-z,A-Z,_ 以外的元字符
str ='_A1bc,123'
run(pattern2,str) #
pattern2 = '\s' # \s 空白字符, 包括换行, 换行在不同的系统是不一样的。 \n,\r,\v,\f
str ='1 234 abc'
run(pattern2,str) #
pattern2 = '\s' # \s 空白字符, 包括换行, 换行在不同的系统是不一样的。 \n,\r,\v,\f
str ='1234\nabc'
run(pattern2,str) #
pattern2 = '\s' # \s 空白字符, 包括换行, 换行在不同的系统是不一样的。 \n,\r,\v,\f
str ='1234\rabc'
run(pattern2,str) #
pattern2 = '\S' # 空白以外的字符
str =' 1234\nabc'
run(pattern2,str) #
pattern2 = '\S' # 空白以外的字符
str ='\r\v\f\nabc'
run(pattern2,str) #
pattern2 = '.' # 任意字符, 除了换行符 .
str ='abc'
run(pattern2,str) #
pattern2 = '.' # 任意字符, 除了换行符 .
str ='1bc'
run(pattern2,str) #
pattern2 = '.' # 任意字符, 除了换行符 .
str ='_bc'
run(pattern2,str) #
pattern2 = '.' # 任意字符, 除了换行符 .
str ='\nbc'
run(pattern2,str) #
原子修饰符。 修饰原子。 可以划分为, 整体修饰,数量修饰,位置修饰和特殊修饰(转义,词边界等
[] : 原子列表。 将多个原子用 [] 包裹表示,满足里面任意个元素即可。
[^] : 排除 原子列表中的元素。
import re
# 定义表达式的调用 函数
# 方便后续的测试
def run(pattern:str,str1:str):
res = re.search(pattern,str1)
print(type(res), res)
patten1 = '[a,b,1,2,A,Z]'
str1 = 'cd1BC'
str2 = 'BCDS'
str3 = 'ab85967'
run(patten1, str1) #
run(patten1, str2) # None
run(patten1, str3) #
pattern2 = '[^0,1,2]' # 除了 012以外的任意 原子
str1 = '012AZ'
str2 = '01'
str3 = '0'
str4 = '3456789azAZ%'
run(pattern2,str1) #
run(pattern2,str2) # None
run(pattern2,str3) # None
run(pattern2,str4) #
修饰前面那个原子的数量
+ : 表示1个以上的数量, 例如 \d+ 表示1个以上的数字 |
? :表示0个 或 1个原子。 例如 \d? |
* :表示任意数量的原子,包括0 |
{m} :表示 m个 原子 |
{m,n}: 表示 m到n个原子, 包含 m和n。 例如 \d{2,5} ,表示 2个到5个数字 |
{m , } : 表示m个以上的原子 |
{ , n} :表示 n个以下的原子 |
代码示例:
import re
# 定义表达式的调用 函数
# 方便后续的测试
def run(pattern:str,str1:str):
res = re.search(pattern,str1)
print(type(res), res)
## 数量修饰 ,
# 1.1 +, 标识 一个以上
pattern2 = 'a+' # + 1个以上.
str ='aabc'
run(pattern2,str) #
pattern2 = 'a+' # + 1个以上.
str ='abc'
run(pattern2,str) #
pattern2 = 'ab+' # + 1个以上. 修饰的是之前那个 元字符, 这里就是 b。 所以结果不是 aaabb, 而是 abb
str ='aaabbc'
run(pattern2,str) #
# 1.2: * , 标识 任意数量, 包括0
pattern2 = 'a*' # * 任意数量
str ='aaabbc'
run(pattern2,str) #
pattern2 = 'a*' # * 任意数量 , 所以返回的是 match对象,以及其他信息。 而不是none
str ='bbc'
run(pattern2,str) #
# 1.3: {m,n} , 指定数量, 左右的值都包括,即 m,n都包括
pattern2 = 'a{2,4}' # a的数量是 2-4 个, str有两个 所以符合。
str ='aabbc'
run(pattern2,str) #
pattern2 = 'a{2,4}' # a的数量是 2-4 个 , 只有一个所以不符合
str ='abbc'
run(pattern2,str) # None
pattern2 = 'a{2,}' # a的数量是 2 - 无穷大
str ='aaaaaaaaabbc'
run(pattern2,str) #
pattern2 = 'a{,2}' # a的数量是 0 - 2个 , 所以返回 match对象,而不是 none
str ='bbc'
run(pattern2,str) #
\A , ^ : 开头位置/起始位置 |
\Z,, $ :结尾位置/以xxx结尾 |
$^ 和 /Z/A的区别是, $^ 可以匹配多行的字符串。 /Z /A 只能匹配一行字符串。即使有多行的字符串,它也只匹配第一行。 |
^若在 [] 里面 [^] , 则表示非的意思。 例如[^1,2,3] , 非1,2,3。处理1,2,3以外的任意 原子。 |
代码示例:
import re
# 定义表达式的调用 函数
# 方便后续的测试
def run(pattern:str,str1:str):
res = re.search(pattern,str1)
print(type(res), res)
# 2. 位置修饰符。
# 开头位置/起始位置 \A , ^ , 必须放在最前面
pattern2 = '^a{,2}' # 以a的数量是 0 - 2个开头
str ='aabbc'
run(pattern2,str) #
pattern2 = '\Aa{,2}' # 以a的数量是 0 - 2个开头
str ='aabbc'
run(pattern2,str) #
pattern2 = 'a^' # ^ 这个必须放在最前面
str ='aabbc'
run(pattern2,str) # None
pattern2 = 'a\A' # 这个必须放在最前面
str ='aabbc'
run(pattern2,str) # None
# 结尾位置/以xxx结尾 \Z, $
# \Z,$ 必须放在最后面
pattern2 = 'a$' # 以a结尾。 即 最后位置的值必须是a
str ='aabbc'
run(pattern2,str) # None
pattern2 = 'a$' # 以a结尾。 即 最后位置的值必须是a
str ='aabbca'
run(pattern2,str) #
pattern2 = '$a' # $,\Z 必须放在结尾位置, 所以这里结果是none
str ='aabbca'
run(pattern2,str) # None
pattern2 = '\Za' # $,\Z 必须放在结尾位置, 所以这里结果是none
str ='aabbca'
run(pattern2,str) # None
pattern2 = 'a\Z' # $,\Z 必须放在结尾位置
str ='aabbca'
run(pattern2,str) #
## \A ^ 和 \Z $ 之间的区别是, ^和$ 可以用于多行
pattern2 = '^a' # ^ 可以适应 多行匹配。 即第二行有 a开头的字符串, 也能匹配到
str ='''
=-34
abc
124
'''
res = re.search(pattern2,str,re.M)
print(type(res), res) #
pattern2 = '\Aa' # \A 只匹配第一行,即使在多行的 re.M 修正下 。 即第二行有 a开头的字符串, 也匹配不到,返回none
str ='''
=-34
abc
124
'''
res = re.search(pattern2,str,re.M)
print(type(res), res) # None
\ :因为正则表达式有很多 特殊字符 \ , * & ^ 等, 有时候字符串需要 表示他们本身的含义,而不是 转义后的意思。
import re # 导入 re模块
#### 正则表达式的应用测试步骤
# 1. 定义 正则表达式
# 2. 定义 检查字符
# 3. 检查
# 定义表达式的调用 函数
# 方便后续的测试
def run(pattern:str,str1:str):
res = re.search(pattern,str1)
print(type(res), res)
########
## 转义修饰
# 因为正则表达式有很多 特殊字符 \ , * & ^ 等, 有时候字符串需要 表示他们本身的含义,而不是 转义后的意思。
# 这时候只要在他们前面价格 转义字符 \ , 就是可以实现。 \. , \*
pattern1 = 'a*' # 表示 匹配任意数量的a
pattern2 = 'a\*' # 表示 要匹配 a*
str1 = 'aaaabcd'
run(pattern1, str1) #
run(pattern2, str1) # None
pattern1 = 'a.' # 表示 a和任意字符
pattern2 = 'a\.' # 表示 要匹配 a.
str1 = 'aaaabcd'
run(pattern1, str1) #
run(pattern2, str1) # None
\b : 表示能够当做 英文单词分隔的符号,即除了字母和数字以外的字符。 在字符串的开头需要 加转义: \\b |
\B :表示字母和 数字 |
import re # 导入 re模块
#### 正则表达式的应用测试步骤
# 1. 定义 正则表达式
# 2. 定义 检查字符
# 3. 检查
# 定义表达式的调用 函数
# 方便后续的测试
def run(pattern:str,str1:str):
res = re.search(pattern,str1)
print(type(res), res)
########
## 词边界修饰
# \b 需要 加转义\ , \\b
str1 = 'this is my house'
str2 = 'this ismy house'
str3 = 'this is$my house'
pattern2 = '\Bmy'
run(pattern2,str1) # None
run(pattern2,str2) #
run(pattern2,str3) # None
pattern2 = '\\Bmy'
run(pattern2,str1) # None
run(pattern2,str2) #
run(pattern2,str3) # None
pattern2 = '\bmy'
run(pattern2,str1) # None
run(pattern2,str2) # None
run(pattern2,str3) # None
pattern2 = '\\bmy' # 需要转义 \ s是的 \b 生效。 不知道为啥\b 必须要加 \ 转义。
run(pattern2,str1) #
run(pattern2,str2) # None
run(pattern2,str3) #
| : 表示选择关系 或。 例如 ab|cd 。 表示 ab 或 cd。 从左向右 满足其中一个即可
1. 表示将多个原子当做一个原子: 通常叫做模式单元或者组
2. 改变表达式的优先级: 例如 ab|cd , | 是最后执行的
a(b|c)d, 表示 abd或 acd, 在() 修饰后, | 是先执行的。
import re # 导入 re模块
#### 正则表达式的应用测试步骤
# 1. 定义 正则表达式
# 2. 定义 检查字符
# 3. 检查
# 定义表达式的调用 函数
# 方便后续的测试
def run(pattern:str,str1:str):
res = re.search(pattern,str1)
print(type(res), res)
########
## 1. 将多个原子当做一个原子, 称为 模式单元或者 组
pattern2 = 'a|(cs)|cd' # a 或 cs 或 cd
str1 = 'abc' # 满足 a
str2 = 'bcs11' # 满足 cs
str3 = 'bcwc'
run(pattern2,str1) #
run(pattern2,str2) #
run(pattern2,str3) # None
## 2. 改变优先级
pattern2 = 'a(b|c)d' # abd, acd . 若不加() ab|cd, 则是 ab,cd 在 | 。 加了括号改变了优先级, a (b|c) d 一起执行, 也就是 执行了 b|c
str1 = 'abc' # 满足 a
str2 = 'abd' # 满足 cs
str3 = 'acd'
run(pattern2,str1) # None
run(pattern2,str2) #
run(pattern2,str3) #
## 3. 将匹配的内存存储到正则对象
## 涉及到后续的 扩展语法 (?:) , 取消单元存储到 对象. 默认存储到对象
设定额外的规则
re.A, 修正正则模式在 ASCII 编码的环境下 |
re.U, 修正正则模式在 UNICODE 编码的环境下,python3的默认编码。可以识别汉字 |
re.S , 修正模式中 . 的含义 。 使得 . 可以包含 \n |
re.M , 修正表达式是否使用多行模式。 即能否匹配多行的字符串。通常和 ^ $搭配使用 |
re.X , 修正表达式使得匹配时,忽视表达式中的空格和注释内容 |
re.I , ignorecase, 修正表达式,忽视 表达式中的大小写。 |
import re # 导入 re模块
#### 正则表达式的应用测试步骤
# 1. 定义 正则表达式
# 2. 定义 检查字符
# 3. 检查
######## 模式修正符 : 在正则表达式的基础上,设定额外的 规则
## 编码修正 re.A re.U
# re.A 使用 ascii 编码 , re.U 使用unicode编码。
# python3 默认使用 UNICODE编码,可以识别 汉字
pattern1 = r'\w'
str1 = '我is谁,who am 我'
res1 = re.findall(pattern1,str1,re.A)
res2 = re.findall(pattern1,str1,re.U) # unicode 可以识别汉字
print(type(res1),res1) # ['i', 's', 'w', 'h', 'o', 'a', 'm']
print(type(res2),res2) # ['我', 'i', 's', '谁', 'w', 'h', 'o', 'a', 'm', '我']
## re.S , 修正 . 。 是的 . 包含 \n
pattern1 = r'.'
str1 = '我\n是谁'
res1 = re.findall(pattern1,str1)
res2 = re.findall(pattern1,str1,re.S)
print(type(res1),res1) # ['我', '是', '谁']
print(type(res2),res2) # ['我', '\n', '是', '谁']
## re.M , 修正模式为 多行模式。 Multi
pattern1 = r'^www' # 以 www 开头的字符串
str1 = 'www.baidu.com\nwww.google.com\nwww.sougou.com'
res1 = re.findall(pattern1,str1)
res2 = re.findall(pattern1,str1,re.M) # 开启多行模式, 匹配多个结果
print(type(res1),res1) # ['www']
print(type(res2),res2) # ['www', 'www', 'www']
## re.X , 修正模式为 匹配时忽略表达式的注释和空格。 verbose
pattern1 = r'www .' # 表达式含空格
str1 = 'www.baidu.com\nwww.google.com\nwww.sougou.com'
res1 = re.findall(pattern1,str1)
res2 = re.findall(pattern1,str1,re.X)
print(type(res1),res1) # []
print(type(res2),res2) # ['www.', 'www.', 'www.']
## re.I, 修正模式为 不区分大小写, ignore
pattern1 = r'wWw' # 表达式含空格
str1 = 'wWw.baidu.com,WWW.google.com,www.sougou.com'
res1 = re.findall(pattern1,str1)
res2 = re.findall(pattern1,str1,re.I) # 忽视大小写, 所有都能匹配到
print(type(res1),res1) # ['wWw']
print(type(res2),res2) # ['wWw', 'WWW', 'www']