python 正则表达式

首先感谢我的老师雨痕。

Python Library: re
正则表达式是处理字符串最重要的一种手段了。

1. 基本信息

特殊字符(需转义处理):
. ^ $ * + ? { } [ ] \ | ( )

字符定义:
• \d: 十进制数字,相当于 [0-9]
• \D: 非数字字符,相当于 [^0-9]
• \s: 空白字符,相当于 [ \t\n\r\f\v]。
• \S: 非空白字符。
• \w: 字母或数字,相当于 [a-zA-Z0-9]。
• \W: 非字母数字。
• .: 任意字符。
• |: 或。
• ^: 非或开始位置。
• $: 结束位置。
• \b: 单词边界(完整单词,而非其他单词中的子串)。
• \B: 非单词边界。
重复:
• *: 0 或 任意个字符。
• ?: 0 或 一个字符。
• +: 1 或 多个字符。
• {n, m}: n 到 m 个字符。
• {n}: n 个字符。
• {n,}: n 到尽可能多的字符。
• {,m}: 相当于 {0,m}。
通常使用添加一个 "?" 来避免贪婪匹配。

 

2. 正则函数

re 有几个重要的函数:
• match(): 匹配字符串开始位置。
• search(): 扫描字符串,找到第一个位置。
• findall(): 找到全部匹配,以列表返回。
• finditer(): 找到全部匹配,以迭代器返回。
match 和 search 仅匹配一次,匹配不到返回 None。

python hljs    19行

>>> import re
>>> s = "12abc345ab"

>>> m = re.match(r"\d+", s)
>>> m.group(), m.span()
('12', (0, 2))

>>> m = re.match(r"\d{3,}", s)
>>> m is None
True

>>> m = re.search(r"\d{3,}", s)
>>> m.group(), m.span()
('345', (5, 8))

>>> m = re.search(r"\d+", s)
>>> m.group(), m.span()
('12', (0, 2))

findall 返回列表(或空列表),finditer 和 match/search 一样返回 MatchObject 对象。

python hljs    17行

>>> ms = re.findall(r"\d+", s)
>>> ms
['12', '345']

>>> ms = re.findall(r"\d{5}", s)
>>> ms
[]

>>> for m in re.finditer(r"\d+", s): print m.group(), m.span()
... 
12 (0, 2)
345 (5, 8)

>>> for m in re.finditer(r"\d{5}", s): print m.group(), m.span()
... 
>>> 

 

3. MatchObject

match、search、finditer 返回的对象 —— MatchObject。
• group(): 返回匹配的完整字符串。
• start(): 匹配的开始位置。
• end(): 匹配的结束位置。
• span(): 包含起始、结束位置的元组。
• groups(): 返回分组信息。
• groupdict(): 返回命名分组信息。

python hljs    20行

>>> >>> m = re.match(r"(\d+)(?P<letter>[abc]+)", s)

>>> m.group()
'12abc'

>>> m.start()
0

>>> m.end()
5

>>> m.span()
(0, 5)

>>> m.groups()
('12', 'abc')

>>> m.groupdict()
{'letter': 'abc'}

group() 可以接收多个参数,用于返回指定序号的分组。

python hljs    35行

>>> m.group(0)
'12abc'

>>> m.group(1)
'12'

>>> m.group(2)
'abc'

>>> m.group(1,2)
('12', 'abc')

>>> m.group(0,1,2)
('12abc', '12', 'abc')

start()、end() 和 span() 同样能接收分组序号。和 group() 一样,序号 0 表示整体匹配结果。

>>> m.start(0), m.end(0)
(0, 5)

>>> m.start(1), m.end(1)
(0, 2)

>>> m.start(2), m.end(2)
(2, 5)

>>> m.span(0)
(0, 5)

>>> m.span(1)
(0, 2)

>>> m.span(2)
(2, 5)
  1. 编译标志

可以用 re.I、re.M 等参数,也可以直接在表达式中添加 "(?iLmsux)" 标志。
• s: 单行。"." 匹配包括还行符在内的所有字符。
• i: 忽略大小写。
• L: 让 "\w" 能匹配当地字符,貌似对中文支持不好。
• m: 多行。
• x: 忽略多余的空白字符,让表达式更易阅读。
• u: Unicode。
试试看。

python hljs    9行

>>> re.findall(r"[a-z]+", "%123Abc%45xyz&")
['bc', 'xyz']

>>> re.findall(r"[a-z]+", "%123Abc%45xyz&", re.I)
['Abc', 'xyz']

>>> re.findall(r"(?i)[a-z]+", "%123Abc%45xyz&")
['Abc', 'xyz']

下面这么写好看多了吧?

python hljs    8行

>>> patter = r"""
...     (\d+) #number
...     ([a-z]+) #letter
... """

>>> re.findall(pattern, "%123Abc\n%45xyz&", re.I | re.S | re.X)
[('123', 'Abc'), ('45', 'xyz')]

 

4. 组操作

(1) 命名组:(?P...)

python hljs    6行

>>> for m in re.finditer(r"(?P<number>\d+)(?P<letter>[a-z]+)", "%123Abc%45xyz&", re.I):
...     print m.groupdict()
...     
{'number': '123', 'letter': 'Abc'}
{'number': '45', 'letter': 'xyz'}

(2) 无捕获组:(?:...)

作为匹配条件,但不返回。

python hljs    6行

>>> for m in re.finditer(r"(?:\d+)([a-z]+)", "%123Abc%45xyz&", re.I):
...     print m.groups()
...     
('Abc',)
('xyz',)

(3) 反向引用:<number> 或 (?P=name)

引用前面的组。

python hljs    17行

>>> for m in re.finditer(r"<a>\w+</a>", "%<a>123Abc</a>%<b>45xyz</b>&"):
...     print m.group()
...     
<a>123Abc</a>

>>> for m in re.finditer(r"<(\w)>\w+</(\1)>", "%<a>123Abc</a>%<b>45xyz</b>&"):
...     print m.group()
...     
<a>123Abc</a>
<b>45xyz</b>

>>> for m in re.finditer(r"<(?P<tag>\w)>\w+</(?P=tag)>", "%<a>123Abc</a>%<b>45xyz</b>&"):
...     print m.group()
...     
<a>123Abc</a>
<b>45xyz</b>

(4) 声明

正声明 (?=...):组内容必须出现在右侧,不返回。
负声明 (?!...):组内容不能出现在右侧,不返回。
反向正声明 (?<=):组内容必须出现在左侧,不返回。
反向负声明 (?<!):组内容不能出现在左侧,不返回。

python hljs    11行

>>> for m in re.finditer(r"\d+(?=[ab])", "%123Abc%45xyz%780b&", re.I):
...     print m.group()
...     
123
780

>>> for m in re.finditer(r"(?<!\d)[a-z]{3,}", "%123Abc%45xyz%byse&", re.I):
...     print m.group()
...     
byse

更多信息请阅读官方文档或更专业的书籍。

 

5. 修改字符串

(1) split: 用 pattern 做分隔符切割字符串。如果用 "(pattern)",那么分隔符也会返回。

python hljs    6行

>>> re.split(r"\W", "abc,123,x")
['abc', '123', 'x']

>>> re.split(r"(\W)", "abc,123,x")
['abc', ',', '123', ',', 'x']

(2) sub: 替换子串。

可指定替换次数。

python hljs    6行

>>> re.sub(r"[a-z]+", "*", "abc,123,x")
'*,123,*'

>>> re.sub(r"[a-z]+", "*", "abc,123,x", 1)
'*,123,x'

subn() 和 sub() 差不多,不过返回 "(新字符串,替换次数)"。

python hljs    3行

>>> re.subn(r"[a-z]+", "*", "abc,123,x")
('*,123,*', 2)

还可以将替换字符串改成函数,以便替换成不同的结果。

python hljs    10行

>>> def repl(m):
...     print m.group()
...     return "*" * len(m.group())
... 

>>> re.subn(r"[a-z]+", repl, "abc,123,x")
abc
x
('***,123,*', 2)

转载于:https://my.oschina.net/u/129706/blog/2396019

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值