re

一. 什么是正则?

  • 正则就是用一堆特殊的符号表达一种特殊的规律。拿这种特殊的符号到一种大的字符串中去比对, 按着这种特定的规律取到你的值。

二. 常用匹配模式

1. 一对一的匹配(非正则匹配)

# 'hello'.replace(old,new)
# 'hello'.find('pattern')

2.正则匹配

话不多说上我喜爱的矮老湿的图:

3. \w与\W

"""
\w: 匹配数字, 字母, 下划线
\W: 匹配非数字, 字母, 下划线
"""
import re

print(re.findall('\w', 'aAbc123_*()-='))  # ['a', 'A', 'b', 'c', '1', '2', '3', '_', '_']
print(re.findall('\w', 'hello_egon-123 '))  # ['h', 'e', 'l', 'l', 'o', '_', 'e', 'g', 'o', 'n', '1', '2', '3']

print(re.findall('\W', 'aAbc123_*()-= '))  # ['*', '(', ')', '-', '=', '']
print(re.findall('\W', 'hello_egon-123 '))  # ['-', ' ']

4. \s与\S

"""
\s: 匹配空白字符(包含: \n, \t, \f==>\x0c, \r, ' ')
	\n: 换行
	\t: 制表符
	\f: 换页
	\r: 回车
	' ': 空格
\S: 匹配非空白字符
"""
import re

print(re.findall('\s', 'aA\rbc\t\n12\f3_*()-= '))  # ['\r', '\t', '\n', '\x0c', ' ']
print(re.findall('\S', 'aA\rbc\t\n12\f3_*()-= '))  # ['a', 'A', 'b', 'c', '1', '2', '3', '_', '*', '(', ')', '-', '=']

5. \d与\D

"""
\d: 匹配数字0~9
\D: 匹配非数字
"""
import re

print(re.findall('\d', 'aA\rbc\t\n12\f3_*()-= '))  # ['1', '2', '3']
print(re.findall('\D', 'aA\rbc\t\n12\f3_*()-= '))  # ['a', 'A', '\r', 'b', 'c', '\t', '\n', '\x0c', '_', '*', '(', ')', '-', '=', ' ']

6. \A与\Z ==> ^与&

"""
\A ==> ^: 匹配字符串开始
\Z ==> &: 匹配字符串结束(注意: \Z遇到换行只匹配换行前的字符, 和\n换行符没有关系, 而是编辑器中的换行. 而&则没有这种限制)
注意: 这种匹配只匹配1个值
"""
import re

print(re.findall('\Aalex', ' alexis alex sb'))  # []

print(re.findall('sb\Z', ' alexis alexsb sb'))  # ['sb']
print(re.findall('sb\Z', ' alexis alex\nsb sb'))
print(re.findall('sb\Z', """alex
alexis
alex
sb
"""))  # [](注意: \Z遇到换行只匹配换行前的字符, 和\n换行符没有关系, 而是编辑器中的换行)

print(re.findall('^alex', 'alexis alex sb'))  # ['alex']
print(re.findall('sb$', 'alexis alex sb'))  # ['sb']
print(re.findall('sb$', """alex
alexis
alex
sb
"""))  # ['sb'](注意: &则没有这种限制)

# 注意: 这种匹配只匹配1个值
print(re.findall('^alex$', 'alexis alex sb'))  # []
print(re.findall('^alex$', 'al       ex'))  # []
print(re.findall('^alex$', 'alex'))  # ['alex']

7. \n与\t

"""
\n: 匹配换行符(提示: 编辑器中的换行显示也会被\n匹配, 因为末尾在换行的末尾默认就有\n, 只是不给你显示出来) 
\t
注意: 当使用\n, \t作为匹配条件的时候, 在匹配结构的字符串前加小r
"""
import re

print(re.findall(r'\n', 'hello egon \n12\n \t3'))  # ['\n', '\n']
print(re.findall(r'\t', 'hello egon\t12\t \n3'))  # ['\t', '\t']

# 提示: 编辑器中的换行显示也会被\n匹配, 因为末尾在换行的末尾默认就有\n, 只是不给你显示出来
print(re.findall(r'\n', """   # \n
egon     # \n
123      # \n
alex     # \n
"""))  # ['\n', '\n', '\n', '\n']

8. .

"""
.: 匹配除了\n之外任意一个字符, 只有指定了re.DOTALL或者re.S后能匹配换行符. re.DOTALL ==> re.S
"""
import re

# 匹配除了\n之外任意一个字符
print(re.findall('a.b', 'a1b a2b a b abbbb a\nb a\tb a*b'))
# ['a1b', 'a2b', 'a b', 'abb', 'a\tb', 'a*b']
print(re.findall('a.b', 'a1b'))  # ['a1b']
print(re.findall('a.b', 'a1b a*b a b aaab'))  # ['a1b', 'a*b', 'a b', 'aab']
print(re.findall('a.b', 'a\nb'))  # []

# 只有指定了re.DOTALL或者re.S后能匹配换行符
print(re.findall('a.b', 'a\nb', re.S))  # ['a\nb']
print(re.findall('a.b', 'a\nb', re.DOTALL))  # ['a\nb']
print(re.findall('a.b', 'a1b a2b a b abbbb a\nb a\tb a*b', re.DOTALL))  # ['a1b', 'a2b', 'a b', 'abb', 'a\b', 'a\tb']

9. *

"""
*: 左侧那一个字符可以没有 或者 重复匹配无穷次.(贪婪匹配)
"""
import re

print(re.findall('ab*', 'bbbbbbb'))  # []
print(re.findall('ab*', 'a'))  # ['a']
print(re.findall('ab*', 'abbbb'))  # ['abbbb']

print(re.findall('ab*', 'a ab abb abbbbbbbb bbbbbbbb'))  # ['a', 'ab', 'abb', 'abbbbbbbb']

10. +

"""
+: 左侧那一个字符必须要有一个 或者 重复匹配无穷次.(贪婪匹配)
"""
import re

print(re.findall('ab+', 'a'))  # []
print(re.findall('ab+', 'abbb'))  # ['abbb']

print(re.findall('ab+', 'a ab abb abbbbbbbb bbbbbbbb'))  # ['ab', 'abb', 'abbbbbbbb']

11. ?

"""
?: 左侧那一个字符可以没有 或者 重复匹配1次. (贪婪匹配)
"""
import re

print(re.findall('ab?', 'a'))  # ['a']
print(re.findall('ab?', 'abbb'))   # ['ab']

print(re.findall('ab?', 'a ab abb abbbbbbbb bbbbbbbb'))  # ['a', 'ab', 'ab', 'ab']

12.

"""
{n,m}: 左侧那一个字符可以匹配n次 或者 重复匹配m次. 
{n}单独的n表示只左边那一个字符必须出现n次, 多一个不行少一个不行.
{1,1} ==> .
{0,1} ==> ?
{0,}  ==> *
{1,}  ==> +
"""
import re

print(re.findall('ab{2,5}', 'a ab abb abbb abbbb abbbbbbbb bbbbbbbb'))  # ['abb', 'abbb', 'abbbb', 'abbbbb']

# {n}
print(re.findall('ab{2}', 'a ab abb abbb abbbb abbbbbbbb bbbbbbbb'))  # ['abb', 'abb', 'abb', 'abb']

13. []

"""
[]: 匹配指定字符一个
# 单组指定
[0-9]: 指定匹配0~9之间的数字. 其中数字范围可以动态, 例: [0-2]表示指定0~2之间的数字
[a-z]: 指定匹配a~z之间的小写字母. 其中小写字母范围可以动态, 例: [a-f]表示指定a~f之间的字母
[A-Z]: 指定匹配A~Z之间的大写字母. 其中大写字母范围可以动态, 例: [A-F]表示指定A~F之间的字母

# 多组指定
[0-3a-cA-C]: 表示指定匹配0~3之间的数字 或者 a~c之间的小写字母 或者 A~C之间的大写字母

# [^]
[^0-9]: 表示指定匹配非0~9之间的数字. (注意: 这里的^代表去反, 与单纯的^只取开头的意思不一样.)

# 在[-]中指定单纯的-字符
[-0-9] 或 [0-9-] 要么写在顶头, 要么写在末尾.

注意: 在[]中的字符都是普通字符
"""
import re

# 需求: 匹配anb  n为数字
print(re.findall('a\db', 'a1111111b a3b a4b a9b aXb a b a\nb'))   # ['a3b', 'a4b', 'a9b']
print(re.findall('a[0-9]b', 'a1111111b a3b a4b a9b aXb a b a\nb'))  # 结果如上

# 需求: 匹配anb  n的范围数字0~5
print(re.findall('a[0-5]b', 'a1111111b a3b a1b a0b a4b a9b aXb a b a\nb'))  # ['a3b', 'a1b', 'a0b', 'a4b']

# 需求: 匹配anb  n可以为数字, 大小写字母
print(re.findall('a[0-9a-zA-Z]b', 'a1111111b axb a3b a1b a0b a4b a9b aXb a b a\nb'))  # ['axb', 'a3b', 'a1b', 'a0b', 'a4b', 'a9b', 'aXb']

# 需求:匹配anb  n为非数字和非大小写字母
print(re.findall('a[^0-9a-zA-Z]b', 'a1111111b axb a3b a1b a0b a4b a9b aXb a b a\nb'))  # ['a b', 'a\nb']

# 需求: 匹配anb  n数字 或者 换行符\n 或者 -符号
print(re.findall('a-b', 'a-b aXb a b a\nb', re.DOTALL))
print(re.findall('a[-0-9\n]b', 'a-b a0b a1b a8b aXb a b a\nb'))  # ['a-b', 'a0b', 'a1b', 'a8b', 'a\nb']

# 注意: 在[]中的字符都是普通字符
print(re.findall('a[-0-9\n*?.]b', 'a-b a0b  a.b a?b a*b a1b a8b aXb a b a\nb'))  # ['a-b', 'a0b', 'a.b', 'a?b', 'a*b', 'a1b', 'a8b', 'a\nb']

14. .* 和 .*?

"""
.* : 默认为贪婪匹配
.*?: 为非贪婪匹配. 推荐使用
"""
import re

# 需求: 获取a与b两者之间中间的任意的值. 中间可以没有, 也可以匹配任意长度的值
print(re.findall('a.*b', 'a1b22222222b a2b aaa2b ab  b'))  # ['a1b22222222b a2b aaa2b ab  b'](.*获取失败)
print(re.findall('a.*?b', 'a1b22222222b a2b aaa2b ab  b'))  # ['a1b', 'a2b', 'aaa2b', 'ab']

15. .*?

"""

"""
import re

# 需求: 取出数字或者浮点数模型的字符串
print(re.findall('\d+\.?\d*', "asdfasdf123as1111111.123dfa12adsf1asdf3"))  # ['123', '1111111.123', '12', '1', '3']
print(re.findall('a.*?c', 'ac a123c aaaac a *123'))      # ['ac', 'a123c', 'aaaac']

16. () 分组

"""
(): 只取括号内的表达式
(?:): 取匹配成功的所有内容,而不仅仅只是括号内的内容
"""
import re


res = '<li><a id="blog_nav_sitehome" class="menu" href="http://www.cnblogs.com/">博客园</a></li>'
print(re.findall('href="(.*?)"', res))      # ['http://www.cnblogs.com/']
print(re.findall('href="(?:.*?)"', res)) # ['href="http://www.cnblogs.com/"']

print(re.findall('(?:ab)+123', 'ababab123 ab1 abab123cd abcdefabab123'))  # ['ababab123', 'abab123', 'abab123']
print(re.findall('compan(?:y|ies)', 'Too many companies have gone bankrupt, and the next one is my company'))
print(re.findall('ale(?:[0-1a-zA-Z])', 'alex aleX ale1 ale2 ale0'))  # ['alex', 'aleX', 'ale1', 'ale0']

17. |

"""
a|b: 表示a和b这2种情况都匹配
"""
import re

res = re.findall('compan(?:ies|y)',
                 'Too many companies have gone bankrupt, and the next one is my company')
print(res)      # ['companies', 'company']

res1 = re.findall('alex|sb', 'alex sb sadfsadfasdfegon alex sb egon')
print(res1)     # ['alex', 'sb', 'alex', 'sb']

18. a|b 和

"""

"""
import re

. 综合

"""

"""
import re

# 匹配


# \# print(re.findall('a\\c','a\c')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常
print(re.findall(r'a\\c', 'a\c'))  # r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义
print(re.findall('a\\\\c', 'a\c'))  # 同上面的意思一样,和上面的结果一样都是['a\\c']

# ():分组
print(re.findall('ab+', 'ababab123'))  # ['ab', 'ab', 'ab']
print(re.findall('(ab)+123', 'ababab123'))  # ['ab'],匹配到末尾的ab123中的ab
print(re.findall('(?:ab)+123', 'ababab123'))  # findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容
print(re.findall('href="(.*?)"', '<a href="http://www.baidu.com">点击</a>'))  # ['http://www.baidu.com']
print(re.findall('href="(?:.*?)"', '<a href="http://www.baidu.com">点击</a>'))  # ['href="http://www.baidu.com"']

# |
print(re.findall('compan(?:y|ies)', 'Too many companies have gone bankrupt, and the next one is my company'))

三. re模块提供的方法介绍

1. re.findall

"""
re.findall: 返回所有满足匹配的结果, 按照顺序依次放入列表中. 如果没有匹配的结果, 返回空列表[].
"""
import re

print(re.findall('e', 'alex make love'))  # ['e', 'e', 'e']
print(re.findall('w', 'alex make love'))  # []

2. re.search

"""
re.search: 只返回第一个匹配的结果. 如果有匹配结果, 返回值是一个re.Match对象, 且可以使用.group()获取匹配的值. 如果没有匹配结果返回None. 如果在没有匹配结果的情况下使用.group()会抛出异常(AttributeError)
"""
import re

print(re.search('e', 'alex make love'))  # <re.Match object; span=(2, 3), match='e'>
print(re.search('e', 'alex make love').group())  # e

print(re.search('w', 'alex make love'))  # None
# print(re.search('w', 'alex make love').group())  # AttributeError: 'NoneType' object has no attribute 'group'

3. re.match

"""
re.match: 在字符串开始处进行匹配. 如果有匹配结果, 返回值是一个re.Match对象, 且可以使用.group()获取匹配的值. 如果没有匹配结果返回None. 如果在没有匹配结果的情况下使用.group()会抛出异常(AttributeError)
提示: 使用re.search可以在匹配规则中的开头使用^来完全替代re.search
"""
import re

print(re.match('a', 'alex make love'))  # <re.Match object; span=(0, 1), match='a'>
print(re.match('a', 'alex make love').group())  # a

print(re.match('e', 'alex make love'))  # None
print(re.match('e', 'alex make love').group())  # AttributeError: 'NoneType' object has no attribute 'group'

4. re.split

"""
re.split: 返回
"""
import re


5. re.sub 和 re.subn

"""

"""
import re


6. re.comple

"""

"""
import re

posted @ 2020-04-01 23:47  给你加马桶唱疏通  阅读(289)  评论(0编辑  收藏  举报