lesson 038 —— re 模块

lesson 038 —— re 模块

关于 re 模块的简单介绍。就其本质而言,正则表达式(Regular Expression 或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

普通字符

大多数字符和字母都会和自身匹配。

>>> re.findall('alvin','yuanaleSxalexwupeiqi')
['alvin']

元字符

元字符:. ^ $ * + ? { } [ ] | ( ) \

1. 元字符之 .

. 是通配符,除了换行符(\n)之外,其它字符全部可以匹配到。注意:一个 . 只能代替一个字符串,不能代表多个。

>>> import re
>>> ret = re.findall('a..in', 'alinjjssalvinsssainmmmallinsxlimaa\-inxxna\r\inllxal\ninnn')
>>> print(ret)
['alvin', 'allin', 'a\\-in', 'a\r\\in']
2. 元字符之 ^

^ 是通配符,表示开头,即以之后的字符开头才匹配。

>>> ret = re.findall('^a..in', 'addinxxalinjjssalvinsssainmmmallinsxlimaa\-inxxna\r\inllxal\ninnn')
>>> print(ret)
['addin']
3. 元字符之 `

$ 是通配符,表示结尾,即以之前的字符结尾才匹配。

>>> ret = re.findall('a..in$', 'addinxxalinjjssalvinsssainmmmallinsxlimaa\-inxxna\r\inllxal\ninnaedin')
>>> print(ret)
['aedin']
4. 元字符之 *

* 表示重复的字符,即匹配紧挨着它的前面的字符 0 次无穷次 [0, +∞]。并且,它是贪婪匹配(即尽可能多的匹配字符)。

>>> ret = re.findall('abc*e', 'abccccccddef')
>>> print(ret)
[]
>>> ret = re.findall('abc*d', 'abccccccddef')
>>> print(ret)
['abccccccd']
>>> ret = re.findall('abc*d', 'abddef')
>>> print(ret)
['abd']
>>> ret = re.findall('abc*', 'abccccccddef')   # 贪婪匹配
>>> print(ret)
['abcccccc']
5. 元字符之 +

+ 同样表示重复的字符,它也是贪婪匹配,但是,它匹配的是它前面的字符 1 次无穷次 [1, +∞]

>>> ret = re.findall('abc+d', 'abccccccddef')
>>> print(ret)
['abccccccd']
>>> ret = re.findall('abc+d', 'abddef')
>>> print(ret)
[]
>>> ret = re.findall('abc+', 'abccccccddef')   # 贪婪匹配
>>> print(ret)
['abcccccc']
6. 元字符之 ?

? 表示匹配它紧挨的前面的字符 0 次或 1 次 [0, 1]。它也是贪婪匹配

>>> ret = re.findall('abc?d', 'abccccccddef')
>>> print(ret)
[]
>>> ret = re.findall('abc?d', 'abcddef')
>>> print(ret)
['abcd']
>>> ret = re.findall('abc?d', 'abddef')
>>> print(ret)
['abd']
>>> ret = re.findall('abc?d', 'acddef')   # 只作用于和它紧挨的那个字符
>>> print(ret)
[]
>>> ret = re.findall('abc?', 'abcccddef')   # 表示贪婪匹配
>>> print(ret)
['abc']
7. 元字符之 {}

{} 表示自己定义字符重复的次数。例:{4} 表示重复 4 次;{1,6} 表示重复 1 次到 6 次;{0,} 表示重复 0 次 到无穷次,相当于 *{1,} 表示重复 1 次到无穷次,相当于 +{0,1} 表示重复 0 次或 1 次,相当于 ?。它的次数也是贪婪匹配

>>> ret = re.findall('abc{4}', 'abdxxabcdxxabccdxxabcccdxxabccccdxxabccccccdxxabccccccccdxxx')
>>> print(ret)
['abcccc', 'abcccc', 'abcccc']
>>> ret = re.findall('abc{1,6}', 'abdxxabcdxxabccdxxabcccdxxabccccdxxabccccccdxxabccccccccdxxx')
>>> print(ret)
['abc', 'abcc', 'abccc', 'abcccc', 'abcccccc', 'abcccccc']
>>> ret = re.findall('abc{0,}', 'abdxxabcdxxabccdxxabcccdxxabccccdxxabccccccdxxabccccccccdxxx')
>>> print(ret)
['ab', 'abc', 'abcc', 'abccc', 'abcccc', 'abcccccc', 'abcccccccc']
>>> ret = re.findall('abc{1,}', 'abdxxabcdxxabccdxxabcccdxxabccccdxxabccccccdxxabccccccccdxxx')
>>> print(ret)
['abc', 'abcc', 'abccc', 'abcccc', 'abcccccc', 'abcccccccc']
>>> ret = re.findall('abc{0,1}', 'abdxxabcdxxabccdxxabcccdxxabccccdxxabccccccdxxabccccccccdxxx')
>>> print(ret)
['ab', 'abc', 'abc', 'abc', 'abc', 'abc', 'abc']
8. 前面的 *, +, ?, {} 等都是贪婪匹配

也就是尽可能的匹配,后面加 ? 可以使其变成惰性匹配

>>> ret = re.findall('abc*?', 'abccccccddef')
>>> print(ret)
['ab']
>>> ret = re.findall('abc+?', 'abccccccddef')
>>> print(ret)
['abc']
>>> ret = re.findall('abc??', 'abccccccddef')
>>> print(ret)
['ab']
>>> ret = re.findall('abc{1,6}?', 'abdxxabcdxxabccdxxabcccdxxabccccdxxabccccccdxxabccccccccdxxx')
>>> print(ret)
['abc', 'abc', 'abc', 'abc', 'abc', 'abc']
9. 元字符之字符集 []

[] 表示匹配其中的任意一个字符,即或的关系。并且只能匹配到其中的一个字符。在字符集中有功能的符号有 -, ^, \- 表示一个范围,如 [0-9], [a-z]^ 表示 取非,如 [^xy], [^a-z]\ 表示转义。

>>> ret = re.findall('x[y,z]m', 'xymxxxzmxxx,mxxxmmmxx')
>>> print(ret)
['xym', 'xzm', 'x,m']
>>> ret = re.findall('x[y*z]m', 'xymxxxzmxxx*mxxxyymxx')   # * 只是一个字符
>>> print(ret)
['xym', 'xzm', 'x*m']

# -: 表示范围
>>> ret = re.findall('q[a-z]', 'q7xxqyzxx')   # 只能匹配其中一个字符
>>> print(ret)
['qy']
>>> ret = re.findall('q[a-z]*', 'qmannux')   # 与 * 搭配使用
>>> print(ret)
['qmannux']
>>> ret = re.findall('q[a-z]*', 'qnfnakff4jfq4xxqmsd')   # 与 * 搭配使用可以匹配到字符集中的 0 次
>>> print(ret)
['qnfnakff', 'q', 'qmsd']

# ^: 表示取非
>>> ret = re.findall('q[^xy]m', 'qxmssq^mssqymssqdmssq9mss')
>>> print(ret)
['q^m', 'qdm', 'q9m']
>>> ret = re.findall('q[^a-z]*', 'qsjfkdj666q876xx')   # 搭配 *, ^ 使用
>>> print(ret)
['q', 'q876']

# \: 表示转义
>>> ret = re.findall('[\d]', '45abchx3')   # \d: 表示取数字
>>> print(ret)
['4', '5', '3']
>>> ret = re.findall('\([^()]*\)', '12+(34*56-54+2*(2-1))')   # 转义圆括号()
>>> print(ret)
['(2-1)']
10. 元字符之转义符 \

反斜杠( \ )后跟元字符去除特殊功能,如 \., \^, \\, \*, \(, \+, \? 等;

反斜杠( \ )后跟普通字符实现特殊的功能,如 \d 等。

  • \d 匹配任何十进制数;相当于类 [0-9]
  • \D 匹配任何非数字字符;相当于类 [^0-9]
  • \s 匹配任何空白字符;相当于类 [\t\n\r\f\v]
  • \S 匹配任何非空白字符;相当于类 [^\t\n\r\f\v]
  • \w 匹配任何字母数字字符;相当于类 [a-zA-Z0-9]
  • \W 匹配任何非字母数字字符;相当于 类 [^a-zA-Z0-9]
  • \b 匹配一个特殊字符边界,比如空格,&#
>>> ret = re.findall('I\b','I am LIST')
>>> print(ret)
[]
>>> ret = re.findall('I\\b', 'hello I am LIST')
>>> print(ret)
['I']
>>> ret = re.findall(r'I\b','I am LIST')
>>> print(ret)
['I']

# 匹配字符 \b
>>> ret = re.findall('I\b','I am LISTI\bhello')
>>> print(ret)
['I\x08']
>>> ret = re.findall('I\\b','I am LISTI\bhello')
>>> print(ret)
['I', 'I']
>>> ret = re.findall('I\b',r'I am LISTI\bhello')
>>> print(ret)
[]
>>> ret = re.findall('I\\b',r'I am LISTI\bhello')
>>> print(ret)
['I', 'I']
>>> ret = re.findall('I\\\\b',r'I am LISTI\bhello')
>>> print(ret)
['I\\b']

\b 在 ASCII 码中有一定有含义,表示退格符,所以,python 中字符串中若含有类似的字符,python 解释器就会把这个字符解释成 ASCII 码中的值,不会是我们输入的字符 \b 。而在字符串前面加上 r,则表示这个字符串我们看到的是什么样子,它就是这个样子,不会把还有特殊含义的字符进行解释,即 python 解释器会将 \b 转化为 \\b 这样存储。所以,对于上面,我们输入 \b,其实传入正则表达式函数的参数是 ASCII 码中的退格符,当我们输入 \\b,python 解释器传给正则表达式的才是正确的 \b,即字符 \b。而在 re 模块中,\b 具有特别的含义,不会转化为对应的 ASCII 码,\f, \\ 等则会转化为对应的 ASCII 码。若传给 re 模块的是 \\b,则经过 re 处理,最后匹配的是字符 \b

038-01

11. 元字符之分组 ()

() 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \(\)

>>> ret = re.findall(r'(ab)+', 'abbb')
>>> print(ret)
['ab']
>>> ret = re.findall('(ab)+', 'ababababbb')
>>> print(ret)
['ab']
# 这里之所以出现的只有一个 `ab`,是因为 re 模块优先显示的是组内的匹配字符串,取消使用 ?:
# 实际它已经是贪婪匹配(如果不是,结果应该是四个 ab)
>>> ret = re.findall('(?:ab)+', 'ababababbb')
>>> print(ret)
['abababab']

# (?P<name>\w+) 模式
>>> ret = re.search('(?P<id>\d{2})/(?P<name>\w{3})', '23/com45/ddd66/xxxx78jishao')
>>> print(ret)
<_sre.SRE_Match object; span=(0, 6), match='23/com'>
>>> print(ret.group())
23/com
>>> print(ret.group('id'))
23
>>> print(ret.group('name'))
com
>>> ret = re.findall('(?P<id>\d{2})/(?P<name>\w{3})', '23/com45/ddd66/xxxx78jishao')
>>> print(ret)
[('23', 'com'), ('45', 'ddd'), ('66', 'xxx')]
12. 元字符之 |

| 表示两项之间的一个选择。要匹配 |,请使用 \|

>>> ret = re.findall('ab|\d', 'rabhdg8sdauubuu888xdd')
>>> print(ret)
['ab', '8', '8', '8', '8']
>>> ret = re.search('ab|\d', 'rabhdg8sdauubuu888xdd')
>>> print(ret.group())
ab
13. 运算符优先级
运算符描述
\转义符
(), (?:), (?=), []圆括号和方括号
*, +, ?, {n}, {n,}, {n,m}限定符
^, $, \任何元字符、任何字符定位点和序列(即:位置和顺序)
|替换,"或"操作 字符具有高于替换运算符的优先级,使得"m|food"匹配"m"或"food"。若要匹配"mood"或"food",请使用括号创建子表达式,从而产生"(m|f)ood"。

方法

  1. re.findall('a', 'alvin yuan'): 返回所有满足匹配条件的结果,放在列表里
  2. re.search('a', 'alvin yuan'): 函数会在字符串内查找模糊匹配,只找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用 group() 方法得到匹配的字符串,如果字符串没有匹配,则返回 None
  3. re.match('a', 'abc').group(): 同 search,不过尽在字符串开头处进行匹配。
  4. re.split('[ab]', 'abcd'): 会按 a 分割得到 ` bcd,再按b**分别**分割得到 cd。所以结果是['', '', 'cd']`。
  5. re.sub('\d', 'A', 'abcde4566fghim777xfsd', 4): 表示将匹配到的字符串替换成另一个字符串,最后的参数表示替换的次数。这个是将数字替换成字母 A,替换四次。不写次数的话默认全部替换。结果是 'abcdeAAAAfghim777xfsd'
  6. re.subn('\d', 'A', 'abcde4566fghim777xfsd'): 与 sub 相同,只是它返回的是一个元组,第一个是替换之后的结果,第二个是替换 的次数,不是总的可以匹配到的次数。结果是 ('abcdeAAAAfghimAAAxfsd', 7)re.subn('\d', 'A', 'abcde4566fghim777xfsd', 4) 的结果是 ('abcdeAAAAfghim777xfsd', 4)
  7. obj = re.compile('\d{3}'): 参数只有一个,是匹配规则。函数作用是将规则进行编译,然后可以用得到的对象匹配字符串。例如:obj.findall('abc1234566ef'),结果是 ['123', '456']对于匹配多次的规则而言,它具有更高的效率。
  8. ret = re.finditer('\d','abc345ujf789dxx'): 将匹配到的结果用一个迭代器返回。查看方法:next(ret) 结果是 <_sre.SRE_Match object; span=(3, 4), match='3'>,查看内容使用 next(ret).group(),结果是 '3'。可以使用 for 查看。
注意:

对于分组的规则匹配,默认优先返回组内的内容,若要取消,可以使用 ?:

>>> ret = re.findall('www\.(baidu|sina)\.com', 'www.baidu.comxxxxdddwww.sina.comddwwwxbaidu.commm')
>>> print(ret)
['baidu', 'sina']
>>> ret = re.findall('www\.(?:baidu|sina)\.com', 'www.baidu.comxxxxdddwww.sina.comddwwwxbaidu.commm')
>>> print(ret)
['www.baidu.com', 'www.sina.com']

转载于:https://www.cnblogs.com/arelive/p/python-38.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值