• 运维特工,战胜心魔!!
  • 有些事情其实没有那么难,只是我们感觉难,走出第一步!
  • 你所浪费的今天,是昨天死去的人奢望的明天!!!
  • 欢迎访问 unixfbi.com 运维特工社区http://unixfbi.com/
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧
  • 运维特工:http://www.unixfbi.com
  • 人生没有白走的路,每一步都算数!!
  • 空杯心态,沉淀自己!

Python正则表达式

Python unixfbi 8个月前 (10-24) 1589次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

Python 正则表达式

[TOC]

一、正则表达式介绍

Python 提供 re 模块,包含所有正则表达式的功能。由于 Python 的字符串本身也用\转义,所以建议 Python 的正则表达式时使用 r 前缀,不用考虑对\转义问题。

例如:

r1 = r"^\d{3,4}-?\d{8}"

正则表达式默认是贪婪模式匹配,也就是匹配尽可能多的字符串。如果想要使用非贪婪模式匹配,需要使用?

1.正则表达式模式

表达式 说明
^ 匹配字符串的开头
$ 匹配字符串的末尾
. 匹配除了"\n"之外的任何单个字符。匹配包含"\n"在内的任何字符,需要使用'[.\n]'的模式
* 匹配 0 个或多个,指定前一个字符可以被匹配 0 次或更多次,而不是只有一次。匹配引擎会试着重复尽可能多的次数
+ 匹配 1 个或更多次。*+区别:*匹配 0 次或更多次,所以可以根本就不出现。+则要求至少出现 1 次
表示可有可无。匹配 0 个或 1 个由前面的正则表达式定义的片段,非贪婪方式
\d 匹配一个数字字符,和[0-9]相同
\D 匹配一个非数字字符。同于[^0-9]
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]
\S 匹配任何非空白字符。等价于[^\f\n\r\t\v]
\w 匹配包括下划线的任何单词字符。等价于[A-Za-z0-9]
\W 匹配任何非单词字符。等价于[^A-Za-z0-9]
\b 匹配一个单词边界,就是指单词和空格间的位置。例如,'er\b'可以匹配"never"中的'er',但不能匹配"verb"中的'er'
\B 匹配非单词边界。和\b 相反
{m} 匹配 m 个前面表达式
{m,} 精确匹配 n 个前面表达式。至少 m 个,"a{1,}"等价于"a+"。"a{0,}"等价于"a*"。"a{0,1}则与 a?相同"
{m,n} 匹配 m 到 n 次由前面正则表达式定义的片段,贪婪模式。至少有 m 个重复,至多有 n 个重复。忽略 m 会认为下边界是 0,忽略 n 的结果将是上边界为无穷大
| 表示或的意思。例如:a|b 表示 a 或者 b
[...] 用来表示一组字符,例如[a-z],[A-Z],[0-9],[a-z0-9A-Z]
[^...] 表示匹配不在[]中的字符,例如[^0-9]匹配数字之外的字符

2.正则表达式修饰符(可选标志)

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。

修饰符 描述
re.l 使匹配对大小写不敏感
re.M 多行匹配,影响^和$
re.S 使"."匹配包括换行在内的所有字符

二、正则表达式函数与方法

方法/属性 作用
match() 决定 re 是否在字符串刚开始的位置匹配
search() 扫描整个字符串,找到这个 re 匹配的位置
findall() 找到 re 匹配的所有子串,并把他们作为一个列表返回
finditer() 找到 re 匹配的所有子串,并把他们作为一个迭代器返回

MatchObject 实例方法:

方法/属性 作用
group() 返回被 RE 匹配的字符串,匹配整个表达式的字符串,group()可以一次输入多个组号,这种情况下返回一个包含哪些组对应值的元组
groups() 返回一个包含所有小组字符串的元祖,从 1 到所含的小组号
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元祖包含匹配(开始,结束)的位置

1.re.match

re.match从字符串的起始位置匹配一个模式,可以使用指定的模式(pattern) ,匹配后面所给的字符串(string) ,如果匹配成功了,则会返回一个叫做 match 对象,否则空对象 None

match(pattern, string, flags=0)
    Try to apply the pattern at the start of the string, returning
    a Match object, or None if no match was found.

pattern:匹配的正则表达式
string:要匹配的字符串
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

>>> import re
>>> re.match('www','www.unixfbi.com')    
<re.Match object; span=(0, 3), match='www'>
>>> re.match('www','www.unixfbi.com').span()
(0, 3)
>>> print(re.match('com','www.unixfbi.com'))
None

group 举例:

#!/usr/bin/env python3
import re
str = "UnixFBI is very good"
matchObj = re.match(r'(.*) is (.*?) .*',str,re.M|re.I)

if matchObj:
   print("matchObj.group(): ",matchObj.group())
   print("matchObj.group(1): ",matchObj.group(1))
   print("matchObj.group(2): ",matchObj.group(2))
   print("matchObj.groups(): ",matchObj.groups())
else:
   print("No match!!!")

输出:

matchObj.group():  UnixFBI is very good
matchObj.group(1):  UnixFBI
matchObj.group(2):  very
matchObj.groups():  ('UnixFBI', 'very')

2.re.search

re.search()在整个字符串 string 中按照 pattern 进行搜索,并返回第一次匹配到的结果。返回的也是 match 对象。
search(pattern, string, flags=0)
Scan through string looking for a match to the pattern, returning
a Match object, or None if no match was found.

>>> import re
>>> re.search('unixfbi','www.unixfbi.com') 
<re.Match object; span=(4, 11), match='unixfbi'>
>>> print(re.search('www','www.unixfbi.com').span())
(0, 3)
>>> print(re.search('com','www.unixfbi.com').span())
(12, 15)

re.match()re.search()的区别
re.match()只匹配字符串的起始位置,如果字符串开始不符合正则表达式,匹配失败并返回 None;
re.search()匹配整个字符串,直到找到一个匹配。

3.re.compile

re 模块提供了一个正则表达式引擎的接口,可以让你将 REstring 编译成对象并用他们来进行匹配。
compile 函数用于编译正则表达式,生成一个正则表达式对象,供 match()和 search()这两个函数使用。
如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,以后可以重复使用时就不需要编译这个步骤了,直接匹配;

>>> import re
>>> r1 = r"\d{3,4}-?\d{8}"
>>> p_tel = re.compile(r1)
>>> p_tel
re.compile('\\d{3,4}-?\\d{8}')
>>> p_tel.findall('0310-12345678')
['0310-12345678']

4.re.findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。如果能匹配到多次,会把多次结果都返回。以列表的形式返回。返回的也是匹配对象。

match 和 search 是匹配一次,findall 匹配所有。

findall(pattern, string, flags=0)
    Return a list of all non-overlapping matches in the string.

    If one or more capturing groups are present in the pattern, return
    a list of groups; this will be a list of tuples if the pattern
    has more than one group.

    Empty matches are included in the result.

举例:

>>> import re
>>> pattern = re.compile(r'\d+')
>>> result1 = pattern.findall('unixfbi 123 Unixfbi 789')
>>> result2 = pattern.findall('akdklfa123ladkfa23423adaf')
>>> print(result1)
['123', '789']
>>> print(result2)
['123', '23423']

5.re.finditer

re.finditer()能够在 string 中搜索模式,并返回一个迭代器。那么我们就可以对这个迭代器调用 next() 方法,返回所有的结果了。
re.finditer()re.findall()类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
因此findall()finditer()相同,只不过findall() 返回的是列表结果。 而finditer()返回的是迭代器。
这在我们做匹配时,如果返回的结果对象非常多时比较有用。免得在内存中生成一个列表对象了,占据了过多的内存空间。

#!/usr/bin/env python3
import re

pattern = re.compile(r'\d+')
result1 = pattern.finditer('unixfbi 123 Unixfbi789adfads456fdf')

for match in result1:
    print(match.group())

输出:

123
789
456

6.常见属性与方法

主要有posendposstart()end()span()
属性:
pos:指定搜索串的起始位置,从哪里开始搜索
endpos:搜索串的结束位置
方法:
start():匹配到的起始位置
end():匹配到的结束位置
span():返回(start(group),end(group))

举例:

>>> import re
>>> m = re.search('unixfbi','www.unixfbi.com')
>>> m.pos
0
>>> m.endpos
15
>>> m.start()
4
>>> m.end()
11
>>> m.span()
(4, 11)
>>> m.group()
'unixfbi'

7.检索和替换

Python 的 re 模块提供了re.sub()用于替换字符串中的匹配项
sub(pattern, repl, string, count=0, flags=0)
Return the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in string by the
replacement repl. repl can be either a string or a callable;
if a string, backslash escapes in it are processed. If it is
a callable, it's passed the Match object and must return
a replacement string to be used.

pattern:正则模式
repl:替换的字符串
string:要被查找替换的原始字符串
count:匹配后替换的最大次数,默认是 0 表示替换所有的匹配

举例:小写替换为大写

>>> url = 'www.unixfbi.com'
>>> re.sub('fbi','FBI',url)
'www.unixFBI.com'

删除字符串中的数字:

>>> url = 'www.unixfbi.com'
>>> url = 'www.u234nix987fbi.com' 
>>> re.sub('\d','',url)
'www.unixfbi.com'

如何替换/tmp/passwd 中的/bin/bash 为/BIN/BASH:

#!/usr/bin/env python3
import re
with open('/tmp/passwd','r') as f:
     str = f.read()

r = re.sub('/bin/bash','/BIN/BASH/',str)
print(r)

输出结果:

root:x:0:0:root:/root:/BIN/BASH/
mha:x:1002:1003::/home/mha:/BIN/BASH/
haproxy:x:188:188:haproxy:/var/lib/haproxy:/sbin/nologin
mha:x:1002:1003::/home/mha:/BIN/BASH/
mha:x:1002:1003::/home/mha:/BIN/BASH/
mha:x:1002:1003::/home/mha:/BIN/BASH/

怎么查看字符串被替换了多少次呢?
re.subn()
subn(pattern, repl, string, count=0, flags=0)
Return a 2-tuple containing (new_string, number).
new_string is the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in the source
string by the replacement repl. number is the number of
substitutions that were made. repl can be either a string or a
callable; if a string, backslash escapes in it are processed.
If it is a callable, it's passed the Match object and must
return a replacement string to be used.

>>> url = 'www.unixfbi.com'
>>> re.subn('i','I',url)
('www.unIxfbI.com', 2)

8.分割

Python 的 re 模块提供了re.split()分割指定的字符串
split(pattern, string, maxsplit=0, flags=0)
Split the source string by the occurrences of the pattern,
returning a list containing the resulting substrings. If
capturing parentheses are used in pattern, then the text of all
groups in the pattern are also returned as part of the resulting
list. If maxsplit is nonzero, at most maxsplit splits occur,
and the remainder of the string is returned as the final element
of the list.

举例:

>>> re.split('\.',url)     
['www', 'unixfbi', 'com']

可以指定分割次数:

>>> url = 'www.unixfbi.com.cn'
>>> re.split('\.',url,2)      
['www', 'unixfbi', 'com.cn']

分割 passwd 文件:

>>> re.split(':',f1.readline()) 
['root', 'x', '0', '0', 'root', '/root', '/bin/bash\n']
>>> re.split(':',f1.readline())
['bin', 'x', '1', '1', 'bin', '/bin', '/sbin/nologin\n']
>>> re.split(':',f1.readline())
['daemon', 'x', '2', '2', 'daemon', '/sbin', '/sbin/nologin\n']

9.分组

Python 正则除了判断是否匹配之外,正则表达式还有提取子串的强大功能。编写正则时使用()来进行分组。
如果正则表达式中定义了分组,就可以在 Match 对象上用group()方法提取出子串来。

>>> pattern = r"(\w{3,10})@(\w+\.com|\.cn)" 
>>> re.match(pattern,'panggp@unixfbi.com')    
<re.Match object; span=(0, 18), match='panggp@unixfbi.com'>
>>> m = re.match(pattern,'panggp@unixfbi.com')
>>> m.group()
'panggp@unixfbi.com'
>>> m.group(1)
'panggp'
>>> m.group(2)
'unixfbi.com'
>>> m.groups()
('panggp', 'unixfbi.com')

使用(\w{3,10})匹配用户名,(\w{3,10})匹配邮箱域名


UnixFBI 运维特工 , 版权所有丨如未注明 , 均为原创丨 转载请务必注明原文链接http://www.unixfbi.com/587.html
喜欢 (0)
[支付宝]
分享 (0)
unixfbi
关于作者:
运维工程师一枚,做有价值的事情!
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址