Python3正则表达式_re模块_教程详解_笔记_完整内容,“.^$*+?{}[


正则表达式,用于在一大堆数据中查找信息,学习后有利于爬虫信息抓取。

 

“. ^ $ * + ? { } [ ] \ | ( )”是元字符(关键字),如要匹配原字符则需加“\”,如“\[”“\\”。为避免与转义符(\n、\b)冲突,可在字符串前加r,即 r"" 或 r'' 。

 

字符
“\d”表示数字
“\D”表示非数字的字符
“\s”表示空白字符,相当于[ \t\n\r\f\v]
“\S”相当于[^ \t\n\r\f\v]
“\w”表示数字或字母
“\W”表示非数字和字母的字符
“.”表示除换行符'\n'外的所有字符,DOTALL模式下可匹配任何字符(包括'\n')
“[]”整体为一个字符,其中的内容表示"或者"关系,同时元字符全部失效。如:[12]表示'1'或'2',[a-z]表示小写字母(包括扩展拉丁字母如 'é'),[A-Za-z]表示所有字母,而[^a]表示除'a'以外的所有字符,[a^]表示'a'或'^'。由于元字符失效,从而可以 '[\n]' 的方式表示回车符等转义符,但复杂情况下仍推荐使用 r""。

 

 

以下字符都不代表实际字符,即所谓零宽度,称为断言
“^”指示行的开头,不代表实际字符,如MULTILINE模式下以“^a”去匹配“b\nab”则span=(2, 3)。若不是MULTILINE,则仅指示字符串开头。
“$”指示行的末尾。同样需要MULTILINE
“\A”指示字符串的开头
“\Z”指示字符串的末尾
“\b”指示词边界,即每个单词的开头和结尾,单词结构中可包括数字和字母,其他字符如空格逗号可以将其分割为一个个单词。可以指示字符串开头。可能与退格符'\b'冲突,加r或使用'\\b'。
“|”表示或者,优先级比普通字符还低,如“phone|tele”表示"phone"或"tele"
而“()”可控制“|”的范围,如“the (phone|tele)”

 

 

 

重复
“*”表示前一个字符重复0~+inf次
“+”表示前一个字符重复1~+inf次
“?”表示前一个字符重复0或1次,可有可无
“{m}”表示前一个字符重复m次
“{a,b}”表示前一个字符重复a~b次,同时“{,b}”表示0~b,“{a,}”表示a~+inf次。注意大括号中不可包含空格,如“{a, b}”是错误的,应为“{a,b}”。

以上符号默认均为贪婪模式,即匹配尽可能多的字符。如果需匹配尽可能少的字符,可在其后加上“?”符号,如“a*?”为非贪婪模式。

“()”可使重复符号作用于其括住的全部字符上,如“(br)*”指'br'重复0~+inf次

 

 


re模块
基本方法:
“p = re.compile(r'ab*')”编译一个匹配器(正则),r'ab*'为匹配规则的表达式(模式)

“m = p.match('abbcabd')”在'abbcabd'中从第一个字符开始匹配,结果保存在match对象中并返回
“m = p.search('abbcabd')”在'abbcabd'中不断向后查找,只返回第一个最先匹配到的内容
“listAll = p.findall('abbcabd')”在'abbcabd'中不断向后查找所有能匹配的内容,并将其以列表的方式返回
“iterAll = p.finditer('abbcabd')”上一种方式的迭代器版本,迭代时才查找并返回内容

“s = m.group()”或“s = m.group(0)”获得匹配的内容
“s = m.start()”获得匹配内容在字符串中的起始索引值,指向匹配内容的第一个字符
“s = m.end()”获得匹配内容在字符串中的终止索引值,指向匹配内容最后一个字符的后一个字符
“s = m.span()”获得匹配内容在字符串中的范围,元组方式返回,范围为左包含而右不包含的
“print(m)”输出匹配的范围和内容

 

 

分组
在正则表达式中把需要的信息用小括号“()”括起来,即可获得它们,称为分组。如:
“p = re.compile(r'\w(\w)(\w+)')”
“m = p.match('This is Python')”
之后“m.group(1)”可返回第一个分组的内容,即'h'
“m.group(2)”可返回第二个分组的内容,即'is'
以此类推
而“m.group()”或“m.group(0)”依然返回匹配到的所有内容,即 'This'
“m.groups()”可将所有分组内容以元组的方式返回,即('h', 'is')

分组编号从左到右,由内而外。如以r'\w((\w)\w+)'匹配'This is Python'则第一个分组内容为 'his',第二个为 'h',groups()得 ('his', 'h')。
“\1”可指代前面第一个分组匹配到的内容,表示“\1”这里必须要再次出现此内容,可用于检测双字(叠词)。如:

p = re.compile(r'\b(\w+)\s+\1\b')
print(p.search('Paris in the the spring').group())


得:'the the'。

 

注意:分组后“findall”和“finditer”只返回分组的内容,若有多个分组则将每次匹配到的各分组内容以元组的方式存储在列表中。

 

 

 

更多分组:
“(?: ... )”中 ' ... ' 处输入的表达式匹配后不会被groups()捕获。可用于不重要信息的重复如 r'(?:the\s?)*'。称为非捕获组
“(?P<gr>...)”可将此分组命名为 'gr' ,之后通过“group('gr')”可获得此分组的内容。称为命名组
同时“(?P=gr)”可指代前面分组名为 'gr' 匹配到的内容,表示“(?P=gr)”这里必须要再次出现此内容。
以上两种表达式的“P”指Python特有。
“m.groupdict()”可返回所有被命名的分组内容,分组名为键(key),分组内容为值(value)
“(?#…)”为注释,可被忽略
“(?(id/name)a|b)”指如果编号为 'id' 的分组或名称为 'name' 的命名组存在,则匹配a表达式,否则匹配b表达式

 


前向断言
“(?=…)”指此处应出现表达式 '...' 所描述的内容,如无则此次匹配失败。匹配成功后,其自身不计入匹配内容,原因是其自身不代表实际字符,即零宽度。这被称为前向肯定断言。如字符串 "What's that?",若以 r"What's(?=\sth)" 匹配之则得 "What's",若以 r"What's(?=\sth)\s\w+[?]$" 匹配之则得 "What's that?"。

“(?!…)”与上一种相反,指此处不应出现表达式 '...' 所描述的内容,如出现则此次匹配失败。这被称为前向否定断言。可用于排除某种文件后缀,如 r'.*[.](?!bat$)[^.]*$' 只可匹配后缀为"bat"

 

 

后向断言
“(?<=…)”为后向肯定断言,与 '(?=...)' 作用基本相同,不计入匹配内容,但其自身可以代表实际字符。如字符串 "It's spam-egg",若以 r"(?<=-)\w+" search之则仍得 "egg"。“(?<=…)”中不可添加重复(\s*、a{1, 4}),但可添加其他内容如 '|'

“(?<!…)”为后向否定断言,与上一种相反,同样不可添加重复

 


标志
可以在re.compile()中增加匹配标志的参数,相当于对匹配方式进行设置。标志可以叠加,在其之间需加上 '|' 按位与运算符,如:“p.compile(r'ab*, re.M|re.I)”

“re.M”设置MULTILINE模式(多行匹配模式),使 '^' 指示行的开头, '$' 指示行的末尾。也可写为“re.MULTILINE”
“re.I”设置IGNORECASE模式,忽略大小写,即大写既可匹配大写也可匹配小写,小写既可匹配小写也可匹配大写。也可写为“re.IGNORECASE”
“re.L”设置LOCALE模式,方便处理本地所使用的拉丁语言。比如 'é' 'ñ' 'ç' 对于西班牙语而言只有 'é' 'ñ' 是字母,但对于法语而言则只有 'é' 'ç' 是字母。未设置re.L时,Python3默认进行 Unicode 匹配,即将 'é' 'ñ' 'ç' 都识别为字母。设置后,则据地区而定。主要影响 '\w' '\W' '\b' '\B' 和大小写忽略(re.I)。也可写为“re.LOCALE”
“re.S”设置DOTALL模式,使 '.' 可匹配任何字符,包括 '\n'。也可写为“re.DOTALL”
“re.A”设置ASCII模式,使默认的 Unicode 匹配变为 ASCII 匹配,影响 '\w' '\W' '\b' '\B' '\s' '\S' 的工作。也可写为“re.ASCI”
“re.U”设置UNICODE模式,与上一个模式相反,也可写为“re.UNICODE”
“re.X”设置VERBOSE模式,可使正则表达式更易读。设置re.X后,表达式中所有空格都将被忽略,并且允许加入注释,指示各部分的含义,也可写为“re.VERBOSE”,如:

1 charref = re.compile(r"""
2  &[#]                # Start of a numeric entity reference
3  (
4      0[0-7]+         # Octal form
5    | [0-9]+          # Decimal form
6    | x[0-9a-fA-F]+   # Hexadecimal form
7  )
8  ;                   # Trailing semicolon
9 """, re.VERBOSE)

若未设置re.X则写为:

1 charref = re.compile("&#(0[0-7]+"
2                      "|[0-9]+"
3                      "|x[0-9a-fA-F]+);")

设置后空格需以 r'\ ' 表示。

 


模块级函数:
可以不编译匹配器(正则)而直接使用相应函数匹配内容,如:
“m = match(r'ab*', 'abbcabd', re.M)”
“m = search(r'ab*', 'abbcabd', re.M)”
“listAll = findall(r'ab*', 'abbcabd', re.M)”
“iterAll = finditer(r'ab*', 'abbcabd', re.M)”
都将表达式放在第一个参数、字符串在第二个参数、标志在第三个参数即可。

 

 

 

正则表达式用于处理字符串的re函数:

“re.split()”可以以正则表达式匹配的内容为分割符,分割字符串。所匹配的字符将被丢弃。
如:
“p = re.compile(r'\W+')”
“listS = p.split("This is short and sweet.")”
结果为:['This', 'is', 'short', 'and', 'sweet', '']

可指定其最大分割次数,如:
“p.split("This is short and sweet.", maxsplit=2)”指split最多分割2两次,
得:['This', 'is', 'short and sweet.']
也可写为“p.split("This is short and sweet.", 2)”

若正则中有捕获分组,则还将返回捕获分组的内容,如:
“p2 = re.compile(r'(\W+)')”
“listS2 = p2.split("This is short and sweet.")”
结果为:['This', ' ', 'is', ' ', 'short', ' ', 'and', ' ', 'sweet', '.', '']

 

 

“re.sub()”可将正则在字符串中匹配到的内容替换为另一个内容。
如:
“p = re.compile('(blue|white|red)')”
“s = p.sub('colour', 'blue socks and red shoes')”
结果为:'colour socks and colour shoes'

sub()同样可指定最大替换次数,如:
“p.sub('colour', 'blue socks and red shoes', count=1)”指sub最多替换1次,
得:'colour socks and red shoes'
也可写为“p.sub('colour', 'blue socks and red shoes', 1)”

所替换成的另一个内容中可引用匹配内容中的分组内容,可写为 '\1' 或 '\g<1>' ,表示引用第一个分组。对于命名组 '(?P<name>...)' 还可写为 '\g<name>' ,如:
“p = re.compile('section{ (?P<name> [^}]* ) }', re.X)”
“p.sub(r'subsection{\1}','section{First}')”
“p.sub(r'subsection{\g<1>}','section{First}')”
“p.sub(r'subsection{\g<name>}','section{First}')”
结果均为:'subsection{First}'

还可为sub()传入一个函数,sub()会将匹配到的每一个内容以match对象的方式,传入函数中,然后将匹配的内容替换为函数的返回值。如:
“p = re.compile(r'\d+')”
“p.sub(func, 'Call 65490 for printing, 49152 for user code.')”
可依次将匹配到的 '65490'、'49152' 作为 match 对象,传入 func 函数。
若 func = lambda m: hex(int(m.group())) ,则得:
'Call 0xffd2 for printing, 0xc000 for user code.'
此方法可将字符串中的各个整数替换为16进制数

 


“subn()”的用法与sub()完全相同,但还会返回替换次数,如:
“p = re.compile('(blue|white|red)')”
“s = p.subn('colour', 'blue socks and red shoes')”
结果为:('colour socks and colour shoes', 2)

 

 

更多方法/函数
“p.fullmatch()”或“re.fullmatch()”用法与match()一样,但要求正则与字符串必须从头到尾完全匹配,否则返回None。相当于在正则末尾加了一个 '\Z'
“p.flags()”获得匹配器p的所有标志,返回值可直接传入compile()
“p.pattern()”获得匹配器p的正则,以字符串形式返回
“re.escape()”可在字符串中的所有元字符前加 '\' ,避免正则转义,如“print(re.escape('https://www.python.org'))”得 "https://www\.python\.org"
“re.purge()”可清除正则表达式的缓存


“(?...)”也可用于设置标记,放在正则前。如 '(?aiLmsux)^asd&' 可为 '^asd&' 开启 re.A ~ re.X 所有标志。实测效果不太理想。

 

 

 

【例题】

1、 找出一个字符串中所有的数字,其中整数用千分位形式表示,即从个位数起,每3位之间加一个逗号,比如1,000,000,小数用定点十进制表示,并且小数点之前至少有一位数字(比如0.618中的0不可省略)。
如:'1,234.56-234.56=1,000'
返回:['1,234.56', '234.56', '1,000']

解:

1 s = r'1,234.56-234.56=1,000'
2  
3 p = re.compile(r"(\d{1,3}(?:,\d{3})*(?:\.\d+)?)")
4 L = p.findall(s)
5 print(L)

 

 


 

参考:

正则表达式HOWTO — Python 3.10.2 文档

re --- 正则表达式操作 — Python 3.10.4 文档

评论关闭