目录
1 关于:re / regex / regular expression
1.2.1 python里一般都默认安装了 re正则模块,可以先查看确认下
1.2.2 如果没有安装,可以按照正则库regex, pip install regex
2.9.2 无论是正则字符串,还是目标字符串,都记得要加 r
3.3.4 使用 re.match() 来测试,数量的不同写法(可以等价)
3.3.5 所以一般返回 re.match() 即可,而不直接返回 re.match().group() ,原因就很明显了
3.6 没有 re.find() ,只有 re.findall()
1 关于:re / regex / regular expression
1.1 什么是正则表达式
- regular expression 正则表达式
- 以下的各种名字都是指的正则表达式
- re
- regex
- regular expression
- 正则表达式是计算机科学的一个概念
- 是一个跨多种编程语言的语言格式,不同的语言里应该都有对应的正则库,而正则的规则是基本相同的。(我猜的 ^ ^ )
1.2 在python中安装正则模块
1.2.1 python里一般都默认安装了 re正则模块,可以先查看确认下
- 查看 regex模块
- pip list
- pip show regex
1.2.2 如果没有安装,可以按照正则库regex, pip install regex
- 导入 re 模块
- 错误写法: pip install re
- 正确写法: pip install regex
1.3 在python中导入 re : import re
- 导入 re 模块
- 模块其实可以认为是一个 .py文件
- 正确写法: import re
2 正则表达式的相关符号
2.1 行定位符
用来描述字符串的边界,1行的边界?全部字符串的边界把? 可以叫做 字符串整体定位符?^ ^
^ #表示字符串开头
$ #表示字符串结尾
2.2 元字符 (注意是 反斜杠\)
\w #匹配 字母,数字,下划线等,还有各自文字,比如汉字
\W #^w 非w
\s # 匹配空格,换行,tab 等几种看不见的内容 也就是:空格 \n \t
\S #^s 非s
\b #begin 单词的开始的意思 如 \bw 匹配单词(不是整个字符串)开始的字母,数字,下划线等,所以 \b不同于 ^
\B #匹配非单词边界,即若某字串出现的单词字串未以空格分割,则不能匹配 ?
\d # 匹配数字
. # 任意字符
三种括号也是有特殊意义的
() #匹配方括号的每个字符,比如(fruit|food)s 表示 fruits|foods
[] # 匹配方括号的任一个字符,比如 [abc] 表示 a,b ,c 都可以
{} # 限定次数符号,看下面
2.3 量词 \次数 \限定符号 : * + ? {}
量词,缺省值
- 如果没有量词,默认就是1个
- \d # 比如\d匹配数字的;量词不写,默认就是1个的意思
其他量词限定
* # 匹配前面的字符0次/无限次
+ # 匹配前面的字符1次/无限次
? # 匹配前面的字符0次/1次
- 但是这里有点注意,?表示量词时是0|1个,
- 常用于 .*? 这种非贪婪模式
- 但是放在其他量词后面表示,非贪婪匹配的意思,尽可能少的匹配
{n} # 匹配前面的字符n次
{n,} # 匹配前面的字符至少n次
{n,m} # 匹配前面的字符 最少n次,最多m次, n-m次之间的都符合
e.g
^/d{8} #匹配8个数字
.*s #非贪婪匹配任意个数字
2.4 字符类/字符集合: 中括号 [ ]
[abcd] # 匹配abcd中的任意一个都可以
[12345] # 匹配1-5中的任意一个都可以
[0-9] # 匹配任意一个数字,等同于\d
[a-z0-9A-Z] # 匹配所有英文字母,数字,几乎等同\w 是\w的子集(不含汉字等)
2.5 排除字符 [^ ]
关键字 ^
/W # 相当于/^w,但是写法不对,必须写在中括号里 [^] 写在外面还是表示字符串开始
[^a-zA-Z] # 相当于非英文字母以外的其他任意字符
2.6 选择字符 |
选择
条件选择 | 表示or的意思
e.g.
^\d{5}|^\d{6}
2.7 转义字符 反斜杠 \
- 转义字符
- 把 普通字符变成特殊意义的字符, n 转成 \n 换行符
- 把 特殊字符变成普通字符, \* 表示 普通字符 * \. 表示 普通字符 .
2.8 分组符号 ()
(fruit|food)s #表示 fruits|foods
([abc]{1,3}){3} #表示 [abc]1到3个,然后再来3个,一会试试
2.9 正则表达式需要用引号"" 包裹起来
2.9.1 如果有特殊符号,表达式前还要注意加 r
- 比如一般的
- ".*?"
- 实际使用时, 如果包含特殊符号,记得使用 r (rawdata)
- r"https://movie.douban.com/apex"
2.9.2 无论是正则字符串,还是目标字符串,都记得要加 r
- 正则字符串
- 目标字符串,
- 都可以加r 表示 不要转义,取原始字符串的意思
2.10 贪婪模式 / 非贪婪模式
贪婪模式
匹配符合条件的最多的字符数
非贪婪模式
匹配符合条件的最少的字符数
非贪婪匹配,如果一直到末尾,往往会匹配一个尽量少的字符串=none 空字符串
?表示量词时是0|1个,但是放在其他量词后面表示,非贪婪匹配的意思,尽可能少的匹配
- .*?
- *?
- ??
- +?
- {n,m}?
例子1:
#E:\work\FangCloudV2\personal_space\2learn\python3\py0005.txt
# re相关
import re
print(re.match(r"aa\d+","aa2323")) #会尽可能多的去匹配\d
print(re.match(r"aa\d+?","aa2323")) #尽可能少的去匹配\d
例子2
#E:\work\FangCloudV2\personal_space\2learn\python3\py0005.txt
# re相关
import re
get1 = re.match(r'1[35678]\d{9}','13111111111')
print (get1)
get1 = re.match(r'1[35678]\d{9}','121111111111')
print (get1)
get1 = re.match(r'1[35678]\d{2}','13111111111')
print (get1)
get1 = re.match(r'1[35678]','13111111111')
print (get1)
get1 = re.match(r'1[35678]?','13111111111')
print (get1)
get1 = re.match(r'1[35678]\d{1,9}','13111111111')
print (get1)
get1 = re.match(r'1[35678]\d{1,9}?','13111111111')
print (get1)
3 正则表达式的方法
3.1 匹配和查找相关
- re.match()
- re.search()
- re.findall()
- re.finditer()
- re.sub()
- re.compile()
- re.split()
3.2 相同点和差别
3.2.1 返回正则对象
- re.compile() # 返回一个正则对象
- 其他的方法都返回, MatchObject 对象
- 要么返回列表,可迭代对象
3.2.2 不同的查找方法
- re.match() #从开头查找
- re.search()
- re.findall() # 返回一个列表
- re.finditer() # 返回可迭代对象
3.2.3 不同的查找方法
- re.sub() #替换
3.2.4 不同的分割方法
- re.split() #分割,返回列表对象
3.3 re.match()
3.3.1 re 里大多数人接触第一个方法
- 语法
- re.match(pattern, string , flags=0)
- 必须从字符串开头开始匹配
- 返回一个对象 ! (包括none)
- 返回 : MatchObject 对象,如果找不到则返回none
- none
- <re.Match object; span=(0, 1), match='1'>
3.3.2 MatchObject 对象的属性/方法
因为 re.match()返回的是一个MatchObject 对象,所以他有些特殊的属性
- re.match()
- # 使用正则对目标字符串,匹配后的内容
- 返回的内容,<re.Match object; span=(0, 1), match='1'>
- 类型:Match object;
- span=(0,1) ,而其实就是 span=(start,end)
- match="1" , 其实就是返回匹配后的字符串 "1" 也就是 re.match.group()
- re.match().span() # 返回的是 使用正则对目标字符串匹配后的内容的字符串长度
- re.match().start() # 返回的是 使用正则对目标字符串匹配后的内容的字符串的开始位
- re.match().end() # 返回的是 使用正则对目标字符串匹配后的内容的字符串的结束位
- re.match().string() # 返回的是 要使用正则去匹配的 目标字符串
- re.match().group() # 返回的是 使用正则对目标字符串匹配后的内容--这个字符串str
#E:\work\FangCloudV2\personal_space\2learn\python3\py0005.txt
# re相关
import re
str1=re.match("^\d","123abc456ABC")
print (str1)
print (type(str1))
print (str1.start())
print (str1.end())
print (str1.span())
print (str1.string)
print (str1.group())
print (type(str1.group()))
3.3.3 re.match() 和 ^ 其实有点意义重复
- 用 re.match() 还需要加 ^ ?不需要,都表示从头开始查找了
- 实测也如此
#E:\work\FangCloudV2\personal_space\2learn\python3\py0005.txt
# re相关
import re
print ("#第1次测试")
str1=re.match("^\d","123abc456ABC")
print (str1.group())
str1=re.match("^\d{1}","123abc456ABC")
print (str1.group())
str1=re.match("^\d{1,}?","123abc456ABC")
print (str1.group())
str1=re.match("^\d?","123abc456ABC")
print (str1.group())
print ("#第2次测试")
str2=re.match("\d","123abc456ABC")
print (str2.group())
str2=re.match("\d{1}","123abc456ABC")
print (str2.group())
str2=re.match("\d{1,}?","123abc456ABC")
print (str2.group())
str2=re.match("\d?","123abc456ABC")
print (str2.group())
3.3.4 使用 re.match() 来测试,数量的不同写法(可以等价)
比如我只用match()匹配字符串开头的一个数字
以下写法是等价的
- \d #会查找至少1个数字,0个会报错
- \d{1} #会查找至少1个数字,0个会报错
- \d{1,}? #会查找至少1个数字,0个会报错
- 但是这里有点注意,?表示量词时是0|1个,但是放在其他量词后面表示,非贪婪匹配的意思,尽可能少的匹配
下面2个和上面的略有差别
- \d? #如果是0个也可以,返回none ,因为? 本身代表0 或者1
- \d{0,} # 如果是0个也可以,返回none
#E:\work\FangCloudV2\personal_space\2learn\python3\py0005.txt
# re相关
import re
print ("#第1次测试")
str1=re.match("^\d","123abc456ABC")
print (str1.group())
str1=re.match("^\d{1}","123abc456ABC")
print (str1.group())
str1=re.match("^\d{1,}?","123abc456ABC")
print (str1.group())
str1=re.match("^\d?","123abc456ABC")
print (str1.group())
print ("#第2次测试")
str2=re.match("\d","123abc456ABC")
print (str2.group())
str2=re.match("\d{1}","123abc456ABC")
print (str2.group())
str2=re.match("\d{1,}?","123abc456ABC")
print (str2.group())
str2=re.match("\d?","123abc456ABC")
print (str2.group())
print ("#第3次测试")
"""
#这几个找不到会报错
str3=re.match("\d","abc456ABC")
print (str3.group())
str3=re.match("\d{1}","abc456ABC")
print (str3.group())
str3=re.match("\d{1,}?","abc456ABC")
print (str3.group())
"""
str3=re.match("\d?","abc456ABC")
print (str3.group())
str3=re.match("\d{0,}","abc456ABC")
print (str3.group())
3.3.5 所以一般返回 re.match() 即可,而不直接返回 re.match().group() ,原因就很明显了
- re.match() # 返回MatchObject 对象,有可能是<> 有可能是none
- re.match().group() #当MatchObject 对象是none时,这里会报错
- re.match().group() # 如果想这么写,一定考虑好错误处理,当MatchObject为none时做好处理
3.3.6 测试正则 re.match()
- 可以用
- try:
- except Exception as e:
- 暂时先不处理错误而抛出异常!
- Exception 要大写首字母
#E:\work\FangCloudV2\personal_space\2learn\python3\py0004.txt
# re相关
import re
i=1
def print_str(strA):
global i
print ("第%s次试验" %i)
i=i+1
try:
print (strA)
print ("")
except Exception as e:
print ("此次有报错",e)
print ("")
print ("#测试身份证号")
#低级错误,半个括号) \d而不是d
str1=re.match("^[0-9]{18}","110102198001017032")
print_str(str1)
str1=re.match("^\d{18}","110102198001017032")
print_str(str1)
str1=re.match("\d{17}(\d|[x])","110102198001017032")
print_str(str1)
str1=re.match("\d{17}(\d?|[x]?)","110102198001017032")
print_str(str1)
str1=re.match("\d{17}\d?","110102198001017032")
print_str(str1)
str1=re.match("^[1-9]\d{16}(\d|[x])","110102198001017032")
print_str(str1)
str1=re.match("^[1-9]\d{16}([0-9]|[x])","110102198001017032")
print_str(str1)
3.4 re.search()
- 语法
- search(pattern, string, flags=0)
- 可以从字符串的任何地方开始查找匹配
- 除了不从 目标字符串开头开始查找,其他和 re.match() 基本一致
- 返回一个对象 ! (包括none)
3.5 Flags标志
在re库中,有一种Flags标志,它可以调整匹配的行为。常用的Flags标志有:
- re.I:忽略大小写匹配
- re.L:做本地化识别(locale-aware)匹配
- re.M:多行匹配,影响 ^ 和 $ 标志
- re.S:使 . 匹配包括换行符在内的所有字符
- re.U:根据Unicode字符集解析字符。这个标志会影响 \w, \W, \b, \B
- re.X:为了增加可读性,忽略空白符号的意义并允许你把横跨多行的正则表达式写成"非括号化"的形式
3.6 没有 re.find() ,只有 re.findall()
- 居然没有 re.find()
- 使用此方法会报错!
3.7 re.findall()
- 语法
- findall(pattern, string, flags=0)
- 返回一个 列表\
- 比如下面的
- re.findall("",str)
- re.findall("",str,re.I)
3.8 re.sub()
- 语法
- sub(pattern, repl, string, count=0, flags=0)
- 在string内部,按正则 pattern 去替换 repl ,数量为 count 次
- 如果不指定数量,默认只替换1次
- 如果指定数量,则替换对应次数
- 但是默认不能识别大小写,需要有参数 re.I 才可以
3.9 re.finditer
- 语法
- re.finditer(pattern, string[, flags=0])
- 返回,一个可迭代对象
- <callable_iterator object at 0x00000282083B4D90>
- 虽然直接看不懂
- 但是可以用循环,取出其中内容
3.10 re.compile()
- 编译正则表达式
- compile(pattern, flags=0)
- re.compile() 和前面的 re的各种方法不同,他不是一个方法,而是生成一个正则规则,然后其他正则方法,re.search() re.match() 等使用这个正则去匹配、
- 但是,暂时和直接 用正则规则写一个"" 字符串的正则规则,比较 compile() 生成的有什么区别,暂时不知道,留着待查
#E:\work\FangCloudV2\personal_space\2learn\python3\py0005.txt
# re相关
import re
str1="abcabcabcABC"
str_pattern=re.compile("a.*?c")
re_content=str_pattern.match(str1)
print(re_content.group())
str1="abcabcabcABC"
get1=re.search("a.*?c",str1)
print(get1.group())
3.11 re.split()
- 分隔
- 语法
- split(pattern, string, maxsplit=0, flags=0)
- 按 pattern 去分割 string,
- maxsplit=0, 默认次数为0,即无限次!!!
- 并且返回一个列表!