正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
例子:https://segmentfault.com/q/1010000005689554/a-1020000005690900
用python的beautifulsoup提取xml文件标签,想用正则表达式匹配两个条件,比如
<test>
<a>111</a>
<c>123</c>
</test>
<test>
<b>222</b>
<c>123</c>
</test>
现在想用正则表达式提取两个标签的内容,就是<a>
标签跟<b>
标签的内容都要取到,请问该如何写这个正则表达式呢?
import re
pat = re.compile(r'<(a|b)>(.*?)</\1>', re.M)
for m in pat.finditer:
print(m.group(2))
说明:
考虑到这里的
<a>
标签没有属性, 如果有, 可用r'<(a|b).*?>(.*?)</\1>'
.m.group(1)
是指标签名, 即a
或者b
.m.group(2)
则是标签内容..*?
是惰性匹配..finditer
是返回匹配的迭代器, 找它费了点时间.因为标签名不确定, 所以结束标签使用
\1
来反向引用标签名, 毕竟开始和结尾标签名要相同.
正则表达式常用操作符
操作符 | 说明 | 实例 |
---|---|---|
. | 表示任何单个字符 | |
[] | 字符集,对单个字符给出取值范围 | [abc]表示a、b、c,[a-z]表示a到z单个字符 |
[^] | 异或符,非字符集,排除单个字符 | [^abc] 表示非a 非b 非c的单个字符 |
* | *前一个字符出线0次或无限次扩展 | abc* 表示ab、abc、abcc、abcccccc等 |
+ | +前一个字符出线1次或无穷多次 | abc+表示abc、abcc、abcccccc等 |
? | 前一个字符出线0次或1次 | abc?表示ab或abc |
| | 或符号,表示左右表示各一个 | a|b 表示a或者b |
{m} | 表示扩展前一个字符m次 | ab{2}c 表示abbc |
{m,n} | 表示扩展前一个字符m到n次(含n次) | ab{1,3}c表示 abc abbc abbbc |
^ | 异或符号没有出现在方括号中,表示字符串匹配开头 | ^abc 表示abc 且在一个字符串的开头部分 |
$ | 表示字符串匹配结尾 | abc$ 表示abc且在一个字符串的结尾部分 |
() | 分组标记,内部只能使用 | | (abc)表示abc,(abc|sfk) 表示abc或者sfk |
\d | 数字,等价于[0-9] | |
\w | 单次字符,相当于[A-Za-z0-9_] |
经典正则表达式
表达式 | 说明 |
---|---|
^[A-Za-z]+$ | 由26个字母组成的字符串 |
^[A-Za-z0-9]+$ | 由26个字母和数字组成的字符串 |
^-?d+$ | 整数字符串 |
^[0-9][1-9][0-9]$ | 正整数字符串 |
[1-9]\d{5} | 中国境内邮政编码 |
[\u4e00 - \u9fa5] | 中文字符 |
re库的基本使用
re库表示raw string类型来表示正则表达式 r’text’ 例如中国境内邮政编码 可以表示为r’[1-9]\d{5}’
其实就是前面加一个小的的
raw string表示不加转义符的字符串
re库主要功能函数
函数 | 说明 |
---|---|
re.search(pattern,string,flags=0) | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 |
re.match() | 从一个字符串的开始位置起匹配正则表达式,返回match对象 |
re.findall() | 搜索字符串,以列表形式返回所有和正则表达式匹配的子串 |
re.split() | 将一个字符串按照正则表达式分割,返回列表形式 |
re.finditer() | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是一个match对象 |
re.sub() | 替换正则表达式的内容 |
flags 主要有三个控制标记。re.I 忽略正则表达式大小写
re.M 作用于异或操作符,匹配每一行的开始进行匹配
re.S .操作符进行作用,匹配所有字符
例子
import re
match = re.search(r'[1-9]\d{5}',"BIT 100081")
if match:
print(match.group(0))
#100081
list = re.findall(r'[1-9]\d{5}',"BIT 100081 CUT 200345")
list #['100081', '200345']
pat = re.compile(r'[1-9]\d{5}')
rst = pat.search("BIT 100081 CUT 200345") #另一种使用方式,先编译后操作
match对象的常用属性:.string 待匹配的文本 .re匹配时使用的正则表达式 .pos匹配正则表达式文本的开始的位置,.endpos 结束位置
还有四个常用方法 : .group(0) 获得匹配后的字符串 .start()匹配字符串在原始字符串的开始位置 .end()匹配字符串在原始字符串的结束位置 .span()返回(.start(),.end())
match = re.search(r'[1-9]\d{5}',"BIT 100081 CUT 200345")
match.string #'BIT 100081 CUT 200345'
match.re # re.compile(r'[1-9]\d{5}', re.UNICODE)
match.pos # 0
match.endpos # 21
match.group(0) #'100081' 只返回第一个匹配结果,如果需要所有匹配结果 用finditer
match.start() #4
match.end() # 10
match.span() #(4, 10)
贪婪匹配和最小匹配
re库默认贪婪匹配,就是返回匹配到的最长的
如果希望最小匹配,如果操作符可以匹配不同长度,在这个操作符后面加一个?就是最小匹配
match = re.search(r'PY.*N','PYANBNCNDN')
match.group(0) #'PYANBNCNDN'
match = re.search(r'PY.*?N','PYANBNCNDN')
match.group(0) #'PYAN'