[Python模块]正则表达式 re模块的使用与实例

很喜欢Python教材中的这句格言:
有些人面临问题时会想:“我知道, 我将使用正则表达式来解决这个问题.”
这让他们面临的问题变成了两个.
---------Jamie Zawinski
正则表达式的确好用,但是复杂的模式难以阅读和维护,与其把花在研究用正则表达式处理复杂的问题上,还不如把时间花在如何写一套清晰,易维护的逻辑上(但是为什么要用,还是因为爽啊)
关于正则表达式的语法,可以参阅我的这篇[学习笔记]正则表达式语法与使用速查

re模块


“我觉得学习是一个循序渐进的过程,所以我不一次性列出所有的函数,这里只列出例子要用的函数.”

函数 描述
compile(pattern,[, flags]) 根据包含正则表达式的字符串创建模式对象
search(pattern,string[, flags]) 在字符串中查找模式
sub(pat, repl, string[, count=0]) 对字符串中域模式pat匹配的子串都替换为repl

函数re.compile()将字符串表示的正则表达式转换为模式对象,提高匹配效率,调用re.search()等函数时,如果使用的是字符串表示的正则表达式,会在内部先转换为模式对象再使用.如果转为模式对象后,则后面每次使用正则表达式都无需进行转换.即re.search(pat,string)等价于pat.search(string)

例如查找"http://www.python.org"中的python并替换为java

import re
line="http://www.python.org"
pat="(?<=\.).+(?=\.)" #两个.之间的内容
patobj=re.compile(pat) #创建模式对象
print(re.search(pat, line))
print(re.search(patobj, line)) #正则表达式与模式对象都能使用
print(patobj.search(line))  
#输出结果
<re.Match object; span=(11, 17), match='python'>
<re.Match object; span=(11, 17), match='python'>
<re.Match object; span=(11, 17), match='python'>

函数re.search在给定字符串中查找第一个与指定pat匹配的子串,如果找到将返回MatchObject(结果为True),否则为None.(结果为False)
观察结果<re.Match object; span=(11, 17), match='python'>,发现MatchObject的匹配子串为'python',起始与终止位置为11,17

替换为java

line1 = re.sub(pat, "java", line) 
line2 = patobj.sub("java", line) 
print(line1)
print(line2)
#输出结果
http://www.java.org
http://www.java.org
函数 描述
match(pattern, string,[, flags]) 在字符串开头匹配模式
split(pattern, string,[, maxsplit=0]) 根据模式来分割字符串
findall(pattern, string) 返回一个列表,其中包含字符串中所有与模式匹配的子串

函数re.match尝试在给定字符串开头查找与正则表达式匹配的子串,和re.search相似,如果找到这样的子串,返回MatchObject,否则返回None
另外,re.match在模式与字符串开头匹配时就返回True,而不要求与整个字符串匹配,如果要求完全匹配,需要在模式末尾加上$,从而将匹配检查延伸到整个字符串.

实例:找出以http协议开头的网址

line1 = "http://www.python.org"
line2 = "ftp://192.168.1.1"
patobj = re.compile("http.*")
print(patobj.match(line1))
print(patobj.match(line2))
print(re.match("w{3}.*",line1)) #不是开头匹配
#输出结果
<re.Match object; span=(0, 21), match='http://www.python.org'>
None
None

函数re.split类似于字符串方法str.split,但使用正则表达式来指定分隔符,而不是固定的分隔符

实例:分割字符串中的网址

text="qq.com, baidu.com,,, python.org   csdn.net"
patobj=re.compile('[, ]+')
print(patobj.split(text))
print(patobj.split(text,1))#指定分割次数maxsplit
#输出结果
['qq.com', 'baidu.com', 'python.org', 'csdn.net']
['qq.com', 'baidu.com,,, python.org   csdn.net']

函数re.findall返回一个列表,其中包含所有与给定模式匹配的子串```

实例:分割java代码行中的所有的单词以及逐个标点

text="public static void main(String[] args){ String str='...I'm fine.And you? --he said.';}"
print(re.findall('[\w]+',text))
print(re.findall('[\W]+',text))
#输出结果
['public', 'static', 'void', 'main', 'String', 'args', 'String', 'str', 'I', 'm', 'fine', 'And', 'you', 'he', 'said']
[' ', ' ', ' ', '(', '[', ']', ' ', ')', '{', ' ', ' ', '=', "'", '.', '.', '.', "'", ' ', '.', ' ', '?', ' ', '-', '-', ' ', '.', "'", ';', '}']

匹配对象和编组

方法 描述
group([group1,…]) 获取与给定子模式(编组)匹配的子串
start([group]) 返回与给定编组匹配的子串的起始位置
end([group]) 返回与给定编组匹配的子串的终止位置(与切片一样,不包含终止位置)
span([group]) 返回与给定编组匹配的子串的起始和终止位置

在模块re中,查找与模式匹配的子串的函数,在找到时返回MatchObject对象.
它包含了:
1.与模式匹配的子串的信息 2.模式的哪部分与子串哪部分匹配的信息.子串部分称为编组
例如: 模式’(I am a (student)) who (live in (Guangzhou))’ 就包含了以下编组:

编组序号 子串
0(整个模式) I am a student who live in Guangzhou
1 I am a student
2 student
3 live in Guangzhou
4 Guangzhou

通过创建这样模式,可以提取出感兴趣,有不同意义的部分

text = "I am a student who live in Guangzhou"
pat = '(I am a (student)) who (live in (Guangzhou))'
for i in range(5):
   print(re.search(pat, text).group(i))
#输出结果
I am a student who live in Guangzhou
I am a student
student
live in Guangzhou
Guangzhou

实例:提取网址中的不同部分

pat = re.compile('(^.*//)(.*)\.(.+)\.(.*?)/(.*)')
text = "http://www.abc.com/docs/index.html"
label = ["[Address]", "[Protocol]", "[Domain]", "[Main]", "[Suffix]", "[Doc]"]
for i in range(6):
    print(label[i], re.search(pat, text).group(i))
#输出
[Address] http://www.abc.com/docs/index.html
[Protocol] http://
[Domain] www
[Main] abc
[Suffix] com
[Doc] docs/index.html
#
text = "https://docs.python.org/3/whatsnew/3.7.html" #更换地址
for i in range(6):
    print(label[i], re.search(pat, text).group(i))
#输出
[Address] https://docs.python.org/3/whatsnew/3.7.html
[Protocol] https://
[Domain] docs
[Main] python
[Suffix] org
[Doc] 3/whatsnew/3.7.html

具体实例:模板替换

在已经标注好相应标签的Java代码中,应用模板转换为HTML代码,这里以转换注释为例

labeled_code = \
    [
        ' [note=/* @author xxx]',
        ' [note=*  @since 1.1]   ',
        ' [note= */]',
        'public boolean isTranslate(int octal , int flags){',
        '[note=//...Some codes to realize]',
        'return true; ',
        '}'
    ]
note_pat = re.compile("\[note=(.+)]")  # 注释模式
for text in labeled_code:
    note_match = note_pat.search(text)  # 返回MatchObject
    if note_match:
        note_text = note_match.group(0)
        note_repl = "<span class='note'> " + note_match.group(1) + " </span>"
        text = text.replace(note_text, note_repl) # 替换注释
    print(text)

输出结果:

 <span class='note'> /* @author xxx </span>
 <span class='note'> *  @since 1.1 </span>   
 <span class='note'>  */ </span>
public boolean isTranslate(int octal , int flags){
<span class='note'> //...Some codes to realize </span>
return true; 
}

加上css选择器和相应标签就能实现语法高亮效果

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.note{
color:#000080;
font-weight:bold;
font-style:italic;}
</style>
</head>
<body>
<pre>
<!--此处填入转换的html代码-->
</pre>
</body>
</html>

效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/xHibiki/article/details/83870641