在IC验证的过程经常需要在海量的log文件中进行文本处理,从而获得我们需要知道的信息,这时正则表达式就是我们的有力工具,我在此总结了常用的正则表达式语法和关键词,并以python为例给出应用示例。
1. 普通字符
除了正则表达式的关键词之外全部都是普通字符,普通字符可以用来匹配它自己。
2. 元字符(matacharacters)
元字符是并非直接用于匹配的字符,而是有特殊含义的字符。元字符用于组成特定的表达式用来匹配复杂的字符串结构。
元字符包括:
.*+?[]^${}|()
2.1 点.
.
表示匹配除了换行符之外的任何单个字符。
例子:
从下面的文本中,选择出所有的国家。
小明是中国的
Tom是美国的
彼得是俄国的
可以使用以下代码:
content = '''小明是中国的
Tom是美国的
彼得是俄国的'''
import re #正则表达式的库
#1. r表示不要按照python语法转义
#2. compile会产生正则表达式的类,我们之后可以对这个类使用各种方法。
p = re.compile(r'.国')
#findall方法,将所有查到的结果组织成字符串列表返回
for one in p.findall(content):
print(one)
运行结果:
中国
美国
俄国
2.2 星号*
*
可以用来表示将前面的运算符重复任意次(包括0次),如果后面没有新的正则表达式则星号的生效范围直到行尾。
例子:从下面文本中,选择出所有逗号之后的内容(包括逗号)
理想是石,敲出星星之火
理想是火,点燃熄灭的灯
理想是灯,照亮来时的路
理想是路,指引你到黎明
可以使用如下代码:
content = '''理想是石,敲出星星之火
理想是火,点燃熄灭的灯
理想是灯,照亮来时的路
理想是路,指引你到黎明'''
import re
p = re.compile(r",.*")
for one in p.findall(content):
print(one)
运行结果:
,敲出星星之火
,点燃熄灭的灯
,照亮来时的路
,指引你到黎明
2.3 加号+
+
可以用来表示将前面的运算符重复任意次(大于0次,注意这也是和*的区别),如果后面没有新的正则表达式则星号的生效范围直到行尾。
例子:从下面文本中,选择出所有逗号之后的内容,如果逗号后面没有内容就忽略(包括逗号)
理想是石,敲出星星之火
理想是火,点燃熄灭的灯
理想是灯,照亮来时的路
理想是路,指引你到黎明
黎明是,
使用如下代码:
content = '''理想是石,敲出星星之火
理想是火,点燃熄灭的灯
理想是灯,照亮来时的路
理想是路,指引你到黎明
黎明是,'''
import re
p = re.compile(r",.+")
for one in p.findall(content):
print(one)
运行结果:
,敲出星星之火
,点燃熄灭的灯
,照亮来时的路
,指引你到黎明
2.4 问号+
?
表示匹配前面的子表达式0次或1次
例子:选择每行逗号后面的1个字符,也包括逗号本身。
理想是石,敲出星星之火
理想是火,点燃熄灭的灯
理想是灯,照亮来时的路
理想是路,指引你到黎明
黎明是,
使用如下代码:
content = '''理想是石,敲出星星之火
理想是火,点燃熄灭的灯
理想是灯,照亮来时的路
理想是路,指引你到黎明
黎明是,'''
import re
p = re.compile(r",.?")
for one in p.findall(content):
print(one)
运行结果:
,敲
,点
,照
,指
,
2.5 花括号-匹配指定次数
花括号表示匹配花括号前面的字符指定的次数。例子:匹配多个字符“深”
庭院深几许?
庭院深深
庭院深深深几许?
使用代码:
import re
content = '''庭院深几许?
庭院深深
庭院深深深几许?'''
p = re.compile(r"深{1,4}")
for one in p.findall(content):
print(one)
运行结果:
深
深深
深深深
2.6 贪婪模式和非贪婪模式
在正则表达式中, ‘*’, ‘+’, ‘?’ 都是贪婪地,使用他们时,会尽可能多的匹配内容 如果想要不适用贪婪模式,可以在贪婪的元字符后面加上?,如.*?
例子:使用贪婪的和非贪婪的正则表达式匹配出尖括号中的内容。
'<html><head><title>Title</title>'
贪婪模式的代码:
source = '<html><head><title>Title</title>'
import re
p = re.compile(r'<.*>')
print(p.findall(source))
运行结果:
['<html><head><title>Title</title>']
非贪婪模式的代码:
source = '<html><head><title>Title</title>'
import re
p = re.compile(r'<.*?>')
print(p.findall(source))
运行结果:
['<html>', '<head>', '<title>', '</title>']
2.7 对元字符的转义
使用可以转义元字符为普通字符。
2.8 字符类型匹配
反斜杠后面接一些字符,表示匹配 某种类型 的一个字符。
比如:
d
匹配0-9之间任意一个数字字符,等价于表达式 [0-9]
D
匹配任意一个不是0-9之间的数字字符,等价于表达式 [^0-9]
s
匹配任意一个空白字符,包括 空格、tab、换行符等,等价于表达式 [tnrfv]
S
匹配任意一个非空白字符,等价于表达式 [^ tnrfv]
w
匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式 [a-zA-Z0-9_]
W
匹配任意一个非文字字符,等价于表达式 [^a-zA-Z0-9_]
2.9 方括号
方括号表示要匹配 指定的几个字符之一。
例如:
-
1.
[abc]
可以匹配a, b, c里面的任意一个字符。等价于[a-c]
。 -
2.
[a-c]
可以匹配任意一个小写字符。[A-B]
可以匹配任意一个大写字符。 -
3. 在方括号内^表示表达式取反,如
[^d]
表示非一个非数字字符。 -
4.
[0-9]
表示任意一个数字字符。
2.10 起始、结束与多行模式
2.10.1 起始及其多行模式
-
1.
^
可以用来匹配文本的起始位置。 -
2. 在单行模式下,
^
用于匹配整个文档的起始位置;在多行模式下,^
用于匹配每一行的起始位置; -
3. python默认为单行模式,使用多行模式时,可以使用
re.compile(r'^d+', re.M)
例子:匹配起始位置的数字:
content = '''001-小明年龄-10
002-小东年龄-9
003-小方年龄-11'''
import re
#p = re.compile(r'^d+', re.M) #多行模式
p = re.compile(r'^d+') #单行模式
for one in p.findall(content):
print(one)
运行结果(多行模式):
001
002
003
运行结果(单行模式):
001
2.10.2 结束及其多行模式
-
1.
$
可以用来匹配文本的起始位置。 -
2. 在单行模式下,
^
用于匹配整个文档的起始位置;在多行模式下,$
用于匹配每一行的起始位置; -
3. python默认为单行模式,使用多行模式时,可以使用
re.compile(r'$d+', re.M)
例子:匹配结束位置的数字:
content = '''001-小明年龄-10
002-小东年龄-9
003-小方年龄-11'''
import re
#p = re.compile(r'd+$', re.M) #多行模式
p = re.compile(r'd+$') #单行模式
for one in p.findall(content):
print(one)
运行结果(单行模式):
11
运行结果(多行模式):
10
9
11
2.11 竖线
竖线表示匹配竖线两边的文本其中之一。
特别要注意的是,竖线在正则表达式的优先级是最低的,这就意味着,竖线隔开的部分是一个整体。比如绿色|橙
表示要匹配是绿色
或者橙
,而不是绿色
或者绿橙
。
content = '''苹果,是绿色的
# 橙子,是橙色的
# 香蕉,是黄色的
# 乌鸦,是黑色的'''
import re
p = re.compile(r'黄|绿|橙|黑') #多行模式
for one in p.findall(content):
print(one)
运行结果:
绿
橙
橙
黄
黑
2.12 括号-分组
在正则表达式中使用括号可以将正则表达式中某些内容按照括号分组,并通过元组返回,而不是像没有括号一样直接将正则表达式匹配的内容直接返回。
例子:将文本中的名字和学号单独提取出来。
小明,学号001
小东,学号002
小方,学号003
代码:
content = '''小明,学号001
小东,学号002
小方,学号003'''
import re
p = re.compile(r'^(.+),.+(d{3})', re.MULTILINE)
for one in p.findall(content):
print(one)
运行结果:
('小明', '001')
('小东', '002')
('小方', '003')
2.13 re库方法split
字符串对象的split方法适用于简单的字符串分割。该方法将正则表达式参数作为分割符,对字符串进行分割,并通过列表的形式返回。
例子:我们需要从下面字符串中提取武将的名字
names = '驱逐舰; 巡洋舰, 航空母舰,运输舰, 核潜艇 护卫舰'
代码如下:
import re
names = '驱逐舰; 巡洋舰, 航空母舰,运输舰, 核潜艇 护卫舰'
namelist = re.split(r'[;,s]s*', names)
print(namelist)
结果:
['驱逐舰', '巡洋舰', '航空母舰', '运输舰', '核潜艇', '护卫舰']
2.14 re库方法sub
使用正则表达式里面的sub方法实现替换字符串。第一个参数是被替换的正则表达式,第二个参数是需要用于替换的字符串,第三个参数是源字符串,返回值是替换后的字符串。格式为:
result_str = re.sub(re_expresion_to_be_replace, str_replace , strings)
例如:
import re
ori_str = "现代海军以战列舰为主力,现代海军以铁甲舰为主力,现代海军以风帆舰为主力"
rlt_str = re.sub(r'.{2}舰',"航空母舰",ori_str)
print(rlt_str)
结果:
现代海军以航空母舰为主力,现代海军以航空母舰为主力,现代海军以航空母舰为主力
发表评论