21. re模块

时光毁灭记忆、已成空白 提交于 2020-03-10 19:30:47

一、正则

1. 字符

元字符 匹配内容
. 匹配出换行外任意字符
\w 匹配字母或数字或下划线
\s 匹配任意空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配指定字符的开始
$ 匹配字符串的结尾
\W 匹配非字母数字下划线
\D 匹配非数字
\S 匹配非空白符
a | b 匹配字符a或字符b
() 匹配括号内的表达式,也是一个组
[...] 匹配字符组中的字符
[^...] 匹配除了字符组中的字符其他所有字符

2. 量词

量词 匹配内容
* 重复0或更多次
+ 重复1或更多次
重复0或1次
{n} 重复n次
{n, } 重复n或更多次
{n, m} 重复n到m次

3. 运用

import re
string_test = "hello"

(1) .
string_1 = re.findall('.', string_test)
print(string_1)
>['h', 'e', 'l', 'l', 'o']

(2) ^
string_2 = re.findall('^h', string_test)
print(string_2)
>['h']

(3) $
string_3 = re.findall('o$', string_test)
print(string_3)
>['o']

(4) * - 当匹配单个字符的时候,会因为匹配0次而出现空字符
string_test = "hello llo lw"
string_1 = re.findall('l*', string_test)
print(string_1)
>['', '', 'll', '', '', 'll', '', '', 'l', '', '']

string_test = "hello llo lw"
string_1 = re.findall('ll*', string_test)
print(string_1)
>['ll', 'll', 'l']

(5) + 
string_test = "hello llo lw"
string_1 = re.findall('l+', string_test)
print(string_1)
>['ll', 'll', 'l']

string_test = "hello llo lw"
string_1 = re.findall('ll+', string_test)
print(string_1)
>['ll', 'll']

(6) ?
string_test = "hello llo lw"
string_1 = re.findall('l?', string_test)
print(string_1)
>['', '', 'l', 'l', '', '', 'l', 'l', '', '', 'l', '', '']

string_test = "hello llo lw"
string_1 = re.findall('ll?', string_test)
print(string_1)
>['ll', 'll', 'l']

(7) {n, }
str1='iii amiiii ssdii iihjf iiifgfdgi '
str2=re.findall('ii{2,}',str1)
print(str2)
>['iii', 'iiii', 'iii']

(8) {, m}
str1='iii amiiii ssdii iihjf iiifgfdgi '
str2=re.findall('ii{,2}',str1)
print(str2)
>['iii', 'iii', 'i', 'ii', 'ii', 'iii', 'i']

(9) {n, m}
str1='iii amiiii ssdii iihjf iiifgfdgi '
str2=re.findall('ii{1,2}',str1)
print(str2)
>['iii', 'iii', 'ii', 'ii', 'iii']

(10) \d
str1='iii amiiii 123er45vg44 '
str2=re.findall(r'\d',str1)
print(str2)
>['1', '2', '3', '4', '5', '4', '4']

(11) \w
str1='iii am_你好iiii 123er45vg44 '
str2=re.findall(r'\w',str1)
print(str2)
>['i', 'i', 'i', 'a', 'm', '_', '你', '好', 'i', 'i', 'i', 'i', '1', '2', '3', 'e', 'r', '4', '5', 'v', 'g', '4', '4']

(12) \s
str1='iii am_你好iiii 123\ner\t45vg44 '
str2=re.findall(r'\s',str1)
print(str2)
>[' ', ' ', '\n', '\t', ' ']

(13) \b
str1='i love python '
str2=re.findall(r'\bon',str1)
str3=re.findall(r'on\b',str1)
print(str2)
print(str3)
>[]
>['on']

(14) \D
str1='i love python12456'
str2=re.findall(r'\D',str1)
print(str2)
>['i', ' ', 'l', 'o', 'v', 'e', ' ', 'p', 'y', 't', 'h', 'o', 'n']

(15) \S
str1='i love python12456\n\t'
str2=re.findall(r'\S',str1)
print(str2)
>['i', 'l', 'o', 'v', 'e', 'p', 'y', 't', 'h', 'o', 'n', '1', '2', '4', '5', '6']

(16) \W
str1='i love ¥%*python12456\n\t'
str2=re.findall(r'\W',str1)
print(str2)
>[' ', ' ', '¥', '%', '*', '\n', '\t']

(17) \B
str1='i love python12456'
str2=re.findall(r'ov\B',str1)
print(str2)
>['ov']

(18) []字符集
str1='i love python12456'
str2=re.findall(r'[a-z]',str1)
print(str2)
>['i', 'l', 'o', 'v', 'e', 'p', 'y', 't', 'h', 'o', 'n']

str1='i love python12456'
str2=re.findall(r'[^\d]',str1)
print(str2)
>['i', ' ', 'l', 'o', 'v', 'e', ' ', 'p', 'y', 't', 'h', 'o', 'n']

(19) |
str1='i love python12456\n\n'
str2=re.findall(r'[\d|\s]',str1)
print(str2)
>[' ', ' ', '1', '2', '4', '5', '6', '\n', '\n']

(20) () 分组-标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。只会匹配括号中的内容
str1='i love python12456\n\n'
str2=re.findall(r'n(\d)',str1)
print(str2)
>['1']

二、贪婪与非贪婪匹配

​ 正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。

1. 贪婪模式

​ 贪婪模式下字符串查找会直接走到字符串结尾去匹配,如果不相等就向前寻找,这一过程称为回溯

import re
str1='<table><td><th>贪婪</th><th>贪婪</th><th>贪婪</th></td></table>贪婪'
str2=re.findall(r'<.*>',str1)
print(str2)

>['<table><td><th>贪婪</th><th>贪婪</th><th>贪婪</th></td></table>']

2. 非贪婪模式

​ 非贪婪模式下会自左向右查找,一个一个匹配不会出现回溯的情况

import re
str1='<table><td><th>贪婪</th><th>贪婪</th><th>贪婪</th></td></table>贪婪'
str2=re.findall(r'<.*?>',str1)
print(str2)
>['<table>', '<td>', '<th>', '</th>', '<th>', '</th>', '<th>', '</th>', '</td>', '</table>']

三、re模块使用

1. re.A(re.ASCII)    
    让\w,\W,\b,\B,\d,\D,\s和\S 执行ASCII-只匹配完整的Unicode匹配代替。这仅对Unicode模式有意义,而对于字节模式则忽略。
    
2. re.I(re.IGNORECASE)    
    执行不区分大小写的匹配;类似的表达式也[A-Z]将匹配小写字母。
    
3. re.L(re.LOCALE)  
    让\w,\W,\b,\B和区分大小写的匹配取决于当前的语言环境。该标志只能与字节模式一起使用。不建议使用此标志,因为语言环境机制非常不可靠,它一次只能处理一种“区域性”,并且仅适用于8位语言环境。默认情况下,Python 3中已为Unicode(str)模式启用了Unicode匹配,并且能够处理不同的语言环境/语言。
    
4. re.M(re.MULTILINE)  
    指定时,模式字符'^'在字符串的开头和每行的开头(紧随每个换行符之后)匹配;模式字符'$'在字符串的末尾和每行的末尾(紧接在每个换行符之前)匹配。默认情况下,'^' 仅在字符串的开头,字符串'$'的末尾和字符串末尾的换行符(如果有)之前立即匹配。
    
5. re.S(re.DOTALL)    
    使'.'特殊字符与任何字符都匹配,包括换行符;没有此标志,'.'将匹配除换行符以外的任何内容。

1. findall(pattern, string, flags=0)

​ findall方法,该方法在字符串中查找模式匹配,将所有的匹配字符串以列表的形式返回,如果文本中没有任何字符串匹配模式,则返回一个空的列表,如果有一个子字符串匹配模式,则返回包含一个元素的列表,所以,无论怎么匹配,我们都可以直接遍历findall返回的结果而不会出错。

import re

re_str = "hello this is python 2.7.13 and python 3.4.5"
pattern = "python [0-9]\.[0-9]\.[0-9]"
result = re.findall(pattern=pattern, string=re_str)
print(result)
>['python 2.7.1', 'python 3.4.5']

# 忽略大小写
re_str = "hello this is python 2.7.13 and Python 3.4.5"
pattern = "python [0-9]\.[0-9]\.[0-9]"
result = re.findall(pattern=pattern, string=re_str, flags=re.IGNORECASE)
print(result)
>['python 2.7.1', 'Python 3.4.5']

2. re.compile(pattern, flags=0)

​ 一般采用编译的方式使用python的正则模块,如果在大量的数据量中,编译的方式使用正则性能会提高很多

import re

re_str = "hello this is python 2.7.13 and Python 3.4.5"
re_obj = re.compile(pattern = "python [0-9]\.[0-9]\.[0-9]",flags=re.IGNORECASE)
res = re_obj.findall(re_str)
print(res)
>['python 2.7.1', 'Python 3.4.5']

3. re.match(pattern, string, flags=0)

​ match方法,类似于字符串中的startwith方法,只是match应用在正则表达式中更加强大,更富有表现力,match函数用以匹配字符串的开始部分,如果模式匹配成功,返回一个SRE_Match类型的对象,如果模式匹配失败,则返回一个None,因此对于普通的前缀匹配

1. 判断data字符串是否以what、数字开头

import re

s_true = "what is a boy"
s_false = "What is a boy"
re_obj = re.compile("what")
print(re_obj.match(string=s_true))
><_sre.SRE_Match object; span=(0, 4), match='what'>
print(re_obj.match(string=s_false))
>None

2. 匹配数字
s_true = "123what is a boy"
s_false = "what is a boy"
re_obj = re.compile("\d+")
print(re_obj.match(s_true))
><_sre.SRE_Match object; span=(0, 3), match='123'>
print(re_obj.match(s_true).start())
>0
print(re_obj.match(s_true).end())
>3
print(re_obj.match(s_true).string)
>123what is a boy
print(re_obj.match(s_true).group())
>123
print(re_obj.match(s_false))
>None

4. re.search(pattern, string, flag=0)

​ search方法,模式匹配成功后,也会返回一个SRE_Match对象,search方法和match的方法区别在于match只能从头开始匹配,而search可以从字符串的任意位置开始匹配,他们的共同点是,如果匹配成功,返回一个SRE_Match对象,如果匹配失败,返回一个None,这里还要注意,search仅仅查找第一次匹配,也就是说一个字符串中包含多个模式的匹配,也只会返回第一个匹配的结果,如果要返回所有的结果,最简单的方法就是findall方法,也可以使用finditer方法

print(re.search('\dcom','www.4comrunoob.5com').group())
>4com

*注:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
* group() 返回被 RE 匹配的字符串
* start() 返回匹配开始的位置
* end() 返回匹配结束的位置
* span() 返回一个元组包含匹配 (开始,结束) 的位置
* group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
import re

a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0))   #123abc456,返回整体
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1))   #123
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2))   #abc
print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3))   #456
>>>group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分

5. re.finditer(pattern, string, flags=0)

​ 搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。找到 RE 匹配的所有子串,并把它们作为一个迭代器返回

import re

re_str = "what is a different between python 2.7.14 and python 3.5.4"
re_obj = re.compile("\d{1,}\.\d{1,}\.\d{1,}")

for i in re_obj.finditer(re_str):
    print(i)
>> <_sre.SRE_Match object; span=(35, 41), match='2.7.14'>
>> <_sre.SRE_Match object; span=(53, 58), match='3.5.4'>

6. re.sub(pattern, repl, string, count)

​ re模块sub方法类似于字符串中的replace方法,只是sub方法支持使用正则表达式

import re

re_str = "what is a different between python 2.7.14 and python 3.5.4"
re_obj = re.compile("\d{1,}\.\d{1,}\.\d{1,}")
print(re_obj.sub("a.b.c",re_str,count=1))
>what is a different between python a.b.c and python 3.5.4

print(re_obj.sub("a.b.c",re_str,count=2))
>what is a different between python a.b.c and python a.b.c

print(re_obj.sub("a.b.c",re_str))
>what is a different between python a.b.c and python a.b.c

7、re.split(pattern, string[, maxsplit])

re模块的split方法和python字符串中的split方法功能是一样的,都是将一个字符串拆分成子字符串的列表,区别在于re模块的split方法能够; maxsplit用于指定最大分割次数,不指定将全部分割
print(re.split('\d+','one1two2three3four4five5'))
>['one', 'two', 'three', 'four', 'five', '']
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!