python--正则表达式

如果不知道正则表达式是什么,可以看一下此篇入门文章
关于正则中的表达式符号和特殊字符,可以看此速查表,部分内容与python的扩展写法有些出入
自己写的正则表达式,也可以用此工具校验一下
python中的一些扩展写法,和速查表的内容有出入的

扩展写法.png

常见的正则表达式属性.png

该文章所使用的python版本为3.5.2


在python中,是使用re模块来支持正则表达式的,使用该模块时,直接引入即可

import re

  • match()函数与search()工作

  • match()函数试图从字符串的起始部分对模式进行匹配
  • search()的工作方式与 match()完全一致,不同之处在于 search()会用它的字符串参数,在任意位置对给定正则表达式模式搜索第一次出现的匹配情况。如果搜索到成功的匹配,就会返回一个匹配对象; 否则, 返回
m = re.match('foo', 'foo')
if m: print(m.group())  #  输出为: foo

m = re.match('foo', 'seafood')  # match只能从起始字符串开始匹配的,所以返回m的值为None

m = re.search('foo', 'seafood')
if m: print(m.group())  #  输出: foo

  • findall()函数和finditer()函数

  • findall()查询字符串中某个正则表达式模式全部的非重复出现情况,返回的是一个list
  • finditer()与findall()类似,不过返回的是一个迭代器而已
s = 'This and that. the and thirty'
print(re.findall(r'(th\w+) and (th\w+)', s, re.I))  #  输出: [('This', 'that'), ('the', 'thirty')]

  • sub()函数和subn()函数

  • 这两个函数是用于实现搜索和替换功能
  • subn()和 sub()作用一样,sub()返回替换后的字符串,但 subn()还返回一个表示替换的总数,替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元组返回。
ret = re.sub('X', 'Mr.Smith', 'attn: X\n\nDear X, \n')
print(ret)  #  'attn: Mr.Smith\n\nDear Mr.Smith, \n'

ret = re.subn('X', 'Mr.Smith', 'attn: X\n\nDear X, \n')
print(ret)  #  ('attn: Mr.Smith\n\nDear Mr.Smith, \n', 2)

  • split()函数

e 模块和正则表达式的对象方法 split()对于相对应字符串的工作方式是类似的,但是与分割一个固定字符串相比,它们基于正则表达式的模式分隔字符串,为字符串分隔功能添加一些额外的威力

DATA = (
    'Mountain View, CA 94040',
    'Sunnyvale, CA',
    'Los Altos, 94023',
    'Cupertino 95014',
    'Palo Alto CA',
)
for datanum in DATA:
    s = re.split(', |(?= (?:\d{5}|[A-Z]{2})) ', datanum)  # 依据城市名或者编码拆分,正则的含义:依据", "(逗号空格)拆分或者依据空格(该空格的左侧是5个数字或者是2个大写字母)
    print(s)

结果:
['Mountain View', 'CA', '94040']
['Sunnyvale', 'CA']
['Los Altos', '94023']
['Cupertino', '95014']
['Palo Alto', 'CA']

  • 一些示例

简单的邮箱地址匹配

patt = '\w+@(\w+\.)?\w+\.com'  # 只能匹配@后面,类似于xxx.com/xxxx.yyy.com的邮箱
m = re.match(patt, 'nobody@xxx.yyy.com')

patt = '\w+@(\w+\.)*\w+\.com'  # 匹配@后面有多个域名的邮箱,类似xxx.xxx.xxx.xxx...com
m = re.match(patt, 'nobody@xxx.yyy.zzz.com')

group()函数的一些示例

re.match('(ab)', 'ab')  # group()==group(1) 相等
re.match('(a)(b)', 'ab') # group():ab  group(1):a  group(2):b
re.match('(a(b))', 'ab') # group():ab  group(1):ab group(2):b
re.match('((a)(b))', 'ab') # group():ab  group(1):ab  group(2):a goup(3):b

m = re.search(r'\bthe', 'bite the dog')  # \b匹配的是单词边界
m = re.search(r'the\b', 'bitethe dog')
m = re.search(r'\Bthe', 'bitethe dog')  # 匹配左侧没有边界的the

使用re.x编写易于查看的正则表达式

# 编写易于查看的正则表达式
# re.X/VERBOSE 标记非常有趣;该标记允许用户通过抑制在正则表达式中使用空白符(除了在字符类中或者在反斜线转义中)来创建更易读的正则表达式
m = re.search(r'''(?x)
\((\d{3})\)
[ ]
(\d{3})
-
(\d{4})
''', '(800) 555-1212')  # 其实和这个等价了m = re.search(r'\((\d{3})\)[ ](\d{3})-(\d{4})','(800) 555-1212'),但是更易于看

# 还可以使用\N,其中 N 是在替换字符串中使用的分组编号
# 将 2/20/91  换成  1991-02-20
m = re.sub(r'(\d{1,2})/(\d{1,2})/(\d{2}|\d{4})', r'19\3-0\1-\2', '2/20/91')

指定group()分组的名称

# (?P<name>) 和 (?P=name)
# 前者通过使用一个名称标识符而不是使用从 1 开始增加到 N 的增量数字来保存匹配,
# 如果使用数字来保存匹配结果,我们就可以通过使用\1,\2 ...,\N \来检索,  可以查看上一个示例
# 大概意思就是: 原来的分组,默认的用group(1),group(2)...去取结果,现在用group('xxx')去取
m = re.search(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})', '(900) 555-1212 abc (600) 666-9898')
print(m.groupdict())  # 输出: {'areacode': '900', 'prefix': '555'}
print(m.group())  # 输出: (900) 555-1212
print(m.group(1), m.group('areacode'))  # 输出:900 900

m = re.sub(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(\d{4})', r'\g<areacode> \g<prefix>-xxxx', '(900) 666-1212')
print(m)  # 输出: 900 666-xxxx
m = re.sub(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(\d{4})', r'\1 \2-xxxx', '(900) 666-1212')  # 与上面的等价
print(m)

指定分组名,并且易于查看的正则表达式

# 下面这种写法,太长,看着太费劲
m = re.match(
    r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?P<number>\d{4}) (?P=areacode)-(?P=prefix)-(?P=number) 1(?P=areacode)(?P=prefix)(?P=number)',
    '(800) 555-1212 800-555-1212 18005551212')
print(bool(m))
# 使用(?x)优化
m = re.match(r'''(?x)
# 匹配 (800) 555-1212
\((?P<areacode>\d{3})\)[ ](?P<prefix>\d{3})-(?P<number>\d{4})

# 匹配空格
[ ]

# 匹配 800-500-1212
(?P=areacode)-(?P=prefix)-(?P=number)

# 匹配空格
[ ]

#匹配18005551212
1(?P=areacode)(?P=prefix)(?P=number)
''', '(800) 555-1212 800-555-1212 18005551212')
print(bool(m))

一串数字,每三个之间加上一个分隔符

# 给一串数字,每三位添加一个'-'
data = '1234567890'
patt = r'((?<=\d)\d{3})+\b'
m = re.search(patt, data)
while m:
    data = data[:m.start()] + '-' + data[m.start():]
    m = re.search(patt, data)
print('添加"-"完毕,结果为:', data)

识别时间

# 左边不能是数字,右边也不能是数字
patt = r'(?<!\d)(2[0-3]{1}|[01]?[0-9]{1}):([0-5]?[0-9]{1}):([0-5]?[0-9]{1})(?!\d)'
m = re.search(patt, 'asc 19:23:23 adfs')
print(m.group(1), m.group(2), m.group(3))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容