Python re表达式备忘

re元字符说明

'.'
点号,在普通模式,它匹配除换行符外的任意一个字符;如果指定了 DOTALL 标记,匹配包括换行符以内的任意一个字符。

'^'
尖尖号,匹配一个字符串的开始,在 MULTILINE 模式下,也将匹配任意一个新行的开始。

'$'
美元符号,匹配一个字符串的结尾或者字符串最后面的换行符

'*'
星号,指定将前面的RE重复0次或者任意多次,而且总是试图尽量多次地匹配。

'+'
加号,指定将前面的RE重复1次或者任意多次,而且总是试图尽量多次地匹配。

'?'
问号,指定将前面的RE重复0次或者1次,如果有的话,也尽量匹配1次。

*?, +?, ??
从前面的描述可以看到'*''+''?'都是贪婪的,所以,可以在后面加个问号,将策略改为非贪婪,只匹配尽量少的RE

{m,n}
m和n都是数字,指定将前面的RE重复m到n次,例如a{3,5}匹配35个连续的a。注意,如果省略m,将匹配0到n个前面的RE;如果省略n,将匹配n到无穷多个前面的RE;当然中间的逗号是不能省略的,不然就变成前面那种形式了。

{m,n}?
前面说的{m,n},也是贪婪的,a{3,5}如果有5个以上连续a的话,会匹配5个,这个也可以通过加问号改变。a{3,5}?如果可能的话,将只匹配3个a。

'\'
反斜杆,转义'*','?'等特殊字符,或者指定一个特殊序列(下面会详述)
由于之前所述的原因,强烈建议用raw字符串来表述正则。

[]
方括号,用于指定一个字符的集合。可以单独列出字符,也可以用'-'连接起止字符以表示一个范围。特殊字符在中括号里将失效,比如[akm$]就表示字符'a''k''m',或'$',在这里$也变身为普通字符了。[a-z]匹配任意一个小写字母,[a-zA-Z0-9]匹配任意一个字母或数字。
注意:在中括号里,+、*、(、)这类字符将会失去特殊含义,仅作为普通字符。反向引用也不能在中括号内使用。

'|'
管道符号,A和B是任意的RE,那么A|B就是匹配A或者B的一个新的RE。任意个数的RE都可以像这样用管道符号间隔连接起来。

(...)
匹配圆括号里的RE匹配的内容,并指定组的开始和结束位置。组里面的内容可以被提取,也可以采用\number这样的特殊序列,被用于后续的匹配。要匹配字面意义上的'('')',可以用反斜杆转义:\(、\),或是包含在反括号内:[(][)]

re.I
re.IGNORECASE

让正则表达式忽略大小写,这样一来,[A-Z]也可以匹配小写字母了。此特性和locale无关。

re.L
re.LOCALE
让\w、\W、\b、\B、\s和\S依赖当前的locale。

re.M
re.MULTILINE
影响'^''$'的行为,指定了以后,'^'会增加匹配每行的开始(也就是换行符后的位置);'$'会增加匹配每行的结束(也就是换行符前的位置)。

re.S
re.DOTALL
影响'.'的行为,平时'.'匹配除换行符以外的所有字符,指定了本标志以后,也可以匹配换行符。

re.U
re.UNICODE
让\w、\W、\b、\B、\d、\D、\s和\S依赖Unicode库。

re.X
re.VERBOSE
运用这个标志,你可以写出可读性更好的正则表达式:除了在方括号内的和被反斜杠转义的以外的所有空白字符,都将被忽略,而且每行中,一个正常的井号后的所有字符也被忽略

这里写图片描述

使用习惯

一种是直接匹配

In [9]: result = re.match(r"hello,\w+","hello,world")

In [10]: result
Out[10]: <_sre.SRE_Match at 0x4288f38>

一种是通过编译,再使用

In [24]: regex  = re.compile(r"hello,\w+")

In [25]: result = regex.match("hello,world")

In [26]: result.groups()
Out[26]: ()

In [27]: result.group()
Out[27]: 'hello,world'

In [28]: result.groups?
Docstring:
groups([default=None]) -> tuple.
Return a tuple containing all the subgroups of the match, from 1.
The default argument is used for groups
that did not participate in the match
Type:      builtin_function_or_method

In [29]: result.group?
Docstring:
group([group1, ...]) -> str or tuple.
Return subgroup(s) of the match by indices or names.
For 0 returns the entire match.
Type:      builtin_function_or_method


In [30]: regex  = re.compile(r"hello,(\w+)")

In [31]: result = regex.match("hello,world")
#返回值是一个tuple
In [32]: result.groups()
Out[32]: ('world',)
#返回值是tuple或者str
In [33]: result.group()
Out[33]: 'hello,world'

第二种编译好的比第一种运行的时间快,而且可以重复使用编译好的正则对象

简单例子

匹配日期

In [3]: regex = re.compile("(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})")

In [6]: result =regex.match("2017-01-12")

In [7]: result.group()
Out[7]: '2017-01-12'

In [8]: result.group(1)
Out[8]: '2017'

In [9]: result.group(2)
Out[9]: '01'

In [10]: result.group(3)
Out[10]: '12'

In [12]: result.group("year")
Out[12]: '2017'

In [13]: result.group("day")
Out[13]: '12'


In [16]: result.groupdict()
Out[16]: {'day': '12', 'month': '01', 'year': '2017'}

匹配用户名

In [50]: re.match("^[a-zA-Z0-9]{3,16}$","avz123").group()
Out[50]: 'avz123'

匹配邮箱

In [76]: re.match("^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$",'1234567890@qq.com').group()
Out[76]: '1234567890@qq.com'

匹配url链接

In [78]: regex = re.compile(r'^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)\/?$',re.X)

In [79]: regex.match('www.baidu.com')
Out[79]: <_sre.SRE_Match at 0x423bf48>

In [80]: regex.match('www.baidu.com').group()
Out[80]: 'www.baidu.com'

In [82]: regex.match('http://www.baidu.com').group()
Out[82]: 'http://www.baidu.com'

In [83]: regex.match('https://www.baidu.com').group()
Out[83]: 'https://www.baidu.com'

In [84]: regex.match('https://www.baidu.com/2.html').group()
Out[84]: 'https://www.baidu.com/2.html'


匹配IPv4地址

In [92]:  regex = re.compile(r'''^(?:(?:25[0-5]
    ...:                       |2[0-4][0-9]
    ...:                       |[1]?[0-9][0-9]?)\.){3}
    ...:                       (?:25[0-5]
    ...:                       |2[0-4][0-9]
    ...:                      |[1]?[0-9][0-9]?)$''', re.X)

In [93]: regex.match("10.1.10.22").group()
Out[93]: '10.1.10.22'

In [94]: regex.match("255.255.255.0").group()
Out[94]: '255.255.255.0'

In [95]: regex.match("255.255.256.0").group()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-95-c87c2f8f246d> in <module>()
----> 1 regex.match("255.255.256.0").group()

AttributeError: 'NoneType' object has no attribute 'group'

匹配MAC地址

In [96]: import random

In [97]: mac = [random.randint(0x00,0x7f),]

In [98]: mac = [random.randint(0x00,0x7f),]

In [99]: mac = [random.randint(0x00,0x7f),]

In [100]: mac = [random.randint(0x00,0x7f),
     ...:        random.randint(0x00,0x7f),
     ...:        random.randint(0x00,0x7f),
     ...:        random.randint(0x00,0x7f),
     ...:        random.randint(0x00,0x7f),
     ...:        random.randint(0x00,0x7f)]

In [101]: mac =":".join(map(lambda x:"%02x" %x,mac))

In [102]: mac
Out[102]: '73:76:22:01:29:6d'

In [105]: regex = re.compile(r"""[0-9a-f]{2}([:])
     ...:                        [0-9a-f]{2}
     ...:                        (\1[0-9a-f]{2})                     {4}$""",re.X)

In [106]: regex.match(mac).group()
Out[106]: '73:76:22:01:29:6d'

匹配运算符

In [107]: import re
     ...: from collections import namedtuple
     ...: tokens = [r'(?P<NUMBER>\d+)',
     ...:            r'(?P<PLUS>\+)',
     ...:            r'(?P<MINUS>-)',
     ...:            r'(?P<TIMES>\*)',
     ...:            r'(?P<DIVIDE>/)',
     ...:            r'(?P<WS>\s+)']
     ...: lex = re.compile('|'.join(tokens))
     ...: Token = namedtuple('Token', ['type', 'value'])
     ...: def tokenize(text):
     ...:      scan = lex.scanner(text)
     ...:      return (Token(m.lastgroup, m.group())
     ...:          for m in iter(scan.match, None) if m.lastgroup != 'WS')
     ...:
     ...: for _t in tokenize('1 + 2* 3 - 4'):
     ...:      print(_t)
     ...:
Token(type='NUMBER', value='1')
Token(type='PLUS', value='+')
Token(type='NUMBER', value='2')
Token(type='TIMES', value='*')
Token(type='NUMBER', value='3')
Token(type='MINUS', value='-')
Token(type='NUMBER', value='4')

修改时间格式

In [112]: re.sub(r"(\d{4})-(\d{2})-(\d{2})",r"\2/\3/\1","2017-01-12")
Out[112]: '01/12/2017'

In [114]: re.sub(r"(\d{4})-(\d{2})-(\d{2})",r"[\2/\3/\1]","2017-01-12")
Out[114]: '[01/12/2017]'

In [113]: re.sub(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})",r"\g<month>/\g<day>/\g<year>","2017-01-12")
Out[113]: '01/12/2017'

匹配时使用函数

In [115]: s = "<@U1EAT8MG9>, <@U0K1MF23Z>"
     ...: ID_NAMES = {'U1EAT8MG9': 'zxc', 'U0K1MF23Z': 'zdy'}
     ...: REGEX_AT = re.compile(r'\<@.*?\>')
     ...: def id_to_name(match):
     ...:      content = match.group()
     ...:      name = ID_NAMES.get(content[2:-1])
     ...:      return '@{}'.format(name) if name else content
     ...:
     ...: print REGEX_AT.sub(id_to_name, s)
     ...:
@zxc, @zdy

参考资料

python正则表达式re模块详细介绍

Python正则备忘单
Python Regular Expression cheatsheet

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值