正则表达式本身是一种小型的、高度专业化的编程语言。Python 的 re 模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作,Python 会将正则表达式转化为字节码,利用 C 语言的匹配引擎进行深度优先的匹配。
参考:
https://www.cnblogs.com/tina-python/p/5508402.html
https://blog.csdn.net/sinat_20791575/article/details/54139404
https://www.cnblogs.com/dreamer-fish/p/5282679.html
re模块中常用功能函数
compile()
re.compile(pattern, flags=0)
编译正则表达式,返回一个 pattern 对象
pattern: 编译时用的表达式字符串
flags: 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:
标志 | 含义 |
---|---|
re.S(DOTALL) | 使.匹配包括换行在内的所有字符 |
re.I(GNORECASE) | 使匹配对大小写不敏感 |
re.L(LOCALE) | 做本地化识别(locale-aware)匹配,法语等 |
re.M(MULTILINE) | 多行匹配,影响^和$ |
re.X(VERBOSE) | 该标志通过给予更灵活的格式以便将正则表达式写得更易于理解 |
re.U | 根据Unicode字符集解析字符,这个标志影响\\w,\\W,\\b,\\B |
prog = re.compile(pattern)
result01 = prog.match(string)
result02 = prog.search(string)
result03 = prog.findall(string)
# 等价于
result = re.match(pattern, string)
match()
re.match(pattern, string, flags=0)
如果字符串的开头能匹配正则表达式,返回对应的 match 对象,否则返回None
search()
re.search(pattern, string, flags=0)
在字符串中查找,是否能匹配正则表达式,若是,返回对应的 match 对象,否则返回None
phoneMatch = re.search(r"(\\d\\d\\d)-(\\d\\d\\d)-(\\d\\d\\d\\d)",
"My number is 111-222-3333")
print(phoneMatch.group())
>>>\'111-222-3333\'
print(phoneMatch.groups())
>>>(\'111\', \'222\', \'3333\')
print(phoneMatch.group(0))
>>>\'111-222-3333\'
print(phoneMatch.group(1))
>>>\'111\'
print(phoneMatch.group(2))
>>>\'222\'
print(phoneMatch.group(3))
>>>\'3333\'
findall()
re.findall(pattern, string, flags=0)
找到 RE 匹配的所有子串,并把它们作为一个列表返回。如果无匹配,返回空列表
re.findall(r"(\\d\\d\\d)-(\\d\\d\\d)-(\\d\\d\\d\\d)",
"My number is 111-222-3333; Your number is 123-555-8899")
>>>[\'111\',\'222\',\'333\']
re.subn(r"n(.*?)er", "aa", "My number is 111-222-3333; Your number is 123-555-8899")
>>>(\'My aa is 111-222-3333; Your aa is 123-555-8899\', 2)
re.findall(r"n.*?er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>[\'number\', \'number\']
finditer()
re.finditer(pattern, string, flags=0)
找到 RE 匹配的所有子串,并把它们作为一个迭代器返回(没啥用)
split()
re.split(pattern, string, maxsplit=0, flags=0)
使用正则表达式分离字符串。如果用括号将正则表达式括起来,那么匹配的字符串也会被列入到list中返回。maxsplit是分离的次数,maxsplit=1分离一次,默认为0,不限制次数
text = "JGood is a handsome boy, he is cool, clever, and so on..."
re.sub(r\'\\s+\', \'-\', text)
>>>\'JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...\'
sub()
re.sub(pattern, repl, string, count=0, flags=0)
找到 RE 匹配的所有子串,并将其用一个不同的字符串替换。可选参数 count 是模式匹配后替换的最大次数;count 必须是非负整数。缺省值是 0 表示替换所有的匹配。如果无匹配,字符串将会无改变地返回
subn()
subn(pattern, repl, string, count=0, flags=0)
返回元组,结果和替换次数
使用总结
-
日常使用search和findall
-
compile基本不用使用
-
match与search与findall的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配
re.match(\'[\\d]\',"abc33") >>>None re.search(\'[\\d]\',"abc33").group() >>>3 re.findall(\'[\\d]\',"abc33") >>>[\'3\', \'3\']
正则表达式符号
-
点号"."
- 点号可以代表任意除\\n以外的字符
- 一个点号代表一个字符,相当于占位符
- chenjunpeng -> chenjun...g
-
星号"*"
- 星号代表它前面的子表达式0次到多次
- chenjunpeng -> chen.*g
- chennnnnnn -> chen*
- chen -> che*
-
问号"?"
- 问好代表它前面的子表达式0次或者1次
- chenjunpeng -> Chinju.?peng
- chenjunpeng -> chenu?junpeng
-
加号"+"
- 加号代表它前面的子表达式1次或者多次
- Batwoman ->Bat(wo)+man
-
花括号{}
- {2,5}
- {2,5}?
- 匹配制定次数
- Batwowowoman ->Bat(wo){2,5}man
-
管道符"|"
-
括号()
- 只要括号里面的内容
- 括号内容相当一个完整的子表达式
-
转义字符" \\ "
- 反斜杠不能单独使用
- 让特殊字符变为普通字符:"\\*"
- 让普通字符变为特殊字符:"\\d" 代表数字
-
启始"^"
-
结尾"$"
-
提取数字
- \\d
- 正则表达式里面,使用 “\\d” 来表示一位数字。这里要强调一下,\\d 虽然是由从左上向右下的斜杠和字母d构成的,但是我们要把\\d看成是一个正则表达式符号整体。从左上向右下的斜杠,名字叫做“反斜杠”,在正则表达式中是作为转义字符,不能单独使用。
- 如果要提取两个数字,我们可以使用 \\d\\d,如果要提取三个数字,我们可以使用\\d\\d\\d,但是问题来了,如果我们不知道有这个数有多少位怎么办呢?就需要使用上一课讲到的 + 号。+ 号可以匹配它前面的符号一次或者多次。所以使用 \\d+,可以表示一个任意位数的数字。
-
提取文本
-
.* 贪心算法
-
.*? 非贪心算法
-
对于文本来说,我们在爬虫中一般使用 .*? 这三个符号来完成。
-
我们知道点号表示任意非换行符的字符,*号表示匹配它前面的字符零次或者任意多次。所以 .* 表示匹配一串任意长度的字符串任意次。这个时候必须在 .* 的前后加其他的符号来限定范围,否则得到的结果就是原来的整个字符串。
-
如果在 .* 的后面加一个问号变成 .*? ,那么可以得到什么样的结果呢?问号表示匹配它前面的符号0次或者1次。于是 .*? 的意思就是,匹配一个能满足要求的最短字符串。
-
换行符\\n隔断处理
-
-
字符类
实例 描述 [Pp]ython 匹配 "Python" 或 "python" rub[ye] 匹配 "ruby" 或 "rube" [aeiou] 匹配中括号内的任意一个字母 [0-9] 匹配任何数字。类似于 [0123456789] [a-z] 匹配任何小写字母 [A-Z] 匹配任何大写字母 [a-zA-Z0-9] 匹配任何字母及数字 [^aeiou] 除了aeiou字母以外的所有字符 [^0-9] 匹配除了数字外的字符 -
特殊字符类
实例 描述 . 匹配除 "\\n" 之外的任何单个字符。要匹配包括 \'\\n\' 在内的任何字符,请使用象 \'[.\\n]\' 的模式。 \\d 匹配一个数字字符。等价于 [0-9]。 \\D 匹配一个非数字字符。等价于 [^0-9]。 \\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \\f\\n\\r\\t\\v]。 \\S 匹配任何非空白字符。等价于 [^ \\f\\n\\r\\t\\v]。 \\w 匹配包括下划线的任何单词字符。等价于\'[A-Za-z0-9_]\'。 \\W 匹配任何非单词字符。等价于 \'[^A-Za-z0-9_]\'。
贪心和非贪心匹配
Python的正则表达式匹配模式默认是贪心匹配
问号模式是非贪心模式
# 贪心
re.search(r"\\d{2,5}", r"123456").group()
>>> \'12345\'
# 非贪心
re.search(r"\\d{2,5}?", r"12346").group()
>>> \'12\'
# 贪心
re.findall(r"n(.*)er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>[\'umber is 111-222-3333; Your numb\']
# 非贪心
re.findall(r"n(.*?)er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>[\'umb\', \'umb\']