标签:是你 第一个 查找 fish com local 语言 除了 单词
有些事情是冥冥之中,命中注定,比如这篇文章------关于正则表达式的两年
可以这样说,这篇文章的一个完整生命周期,整整持续了大概两年。
开始回忆 ——
[ 参考链接:https://www.cnblogs.com/dreamer-fish/p/5282679.html]
1 import re 2 re.match #从开始位置开始匹配,如果开头没有则无 3 re.search #搜索整个字符串 4 re.findall #搜索整个字符串,返回一个list
5 # r 用在pattern之前,表示单引号中的字符串为原生字符,不会进行任何转义
1 >>> import re 2 >>> s=‘123abc456eabc789‘ 3 >>> re.findall(r’abc’,s) 4 5 结果就是: 6 [‘abc‘, ‘abc‘]
这里用到的函数 ”findall(rule , target [,flag] )” 是个比较直观的函数,就是在目标字符串中查找符合规则的字符串。第一个参数是规则,第二个参数是目标字符串,后面还可以跟一个规则选项。返回结果结果是一个列表, 中间存放的是符合规则的字符串。如果没有符合规则的字符串被找到,就返回一个空列表。
匹配除换行符 ’/n’ 外的所有字符。如果使用了 ’S’ 选项,匹配包括 ’/n’ 的所有字符。
例:
1 >>> s=’123 /n456 /n789’ 2 >>> findall(r‘.+’,s) 3 [‘123‘, ‘456‘, ‘789‘] 4 5 >>> re.findall(r‘.+’ , s , re.S) 6 [‘123/n456/n789‘]
注意 ’^’ 不能在‘ [ ] ’中,否则含意就发生变化。 在多行模式下,它们可以匹配每一行的行首和行尾。
这是一个以 ’\’ 开头的转义字符, ’\d’ 表示匹配一个数字,即等价于 [0-9]
这个是上面的反集,即匹配一个非数字的字符,等价于 [^0-9] 。注意它们的大小写。
匹配所有的英文字母和数字,即等价于 [a-zA-Z0-9] 。
即 ’\w’ 的补集,等价于 [^a-zA-Z0-9] 。
即匹配空格符、制表符、回车符等表示分隔意义的字符,它等价于 [ /t/r/n/f/v] 。(注意最前面有个空格 )
即间隔符的补集,等价于 [^ /t/r/n/f/v]
匹配字符串的开头。它和 ’^’ 的区别是, ’\A’ 只匹配整个字符串的开头,即使在 ’M’ 模式下,它也不会匹配其它行的很首。
匹配字符串的结尾。它和 ’$’ 的区别是, ’\Z’ 只匹配整个字符串的结尾,即使在 ’M’ 模式下,它也不会匹配其它行的行尾。
它匹配一个单词的边界,比如空格等,不过它是一个‘ 0 ’长度字符,它匹配完的字符串不会包括那个分界的字符。而如果用 ’\s’ 来匹配的话,则匹配出的字符串中会包含那个分界符。
和 ’\b’ 相反,它只匹配非边界的字符。它同样是个 0 长度字符。
当你要将一部分规则作为一个整体对它进行某些操作,比如指定其重复次数时,你需要将这部分规则用 ’(?:’ ‘)’ 把它包围起来,而不能仅仅只用一对括号,那样将得到绝对出人意料的结果。
Python 允许你在正则表达式中写入注释,在 ’(?#’ ‘)’ 之间的内容将被忽略。
正则式需要匹配不定长的字符串,那就一定需要表示重复的指示符。 Python 的正则式表示重复的功能很丰富灵活。重复规则的一般的形式是在一条字符规则后面紧跟一个表示重复次数的规则,已表明需要重复前面的规则一定的次数。重复规则有:
表示匹配前面的规则 0 次或多次。
表示匹配前面的规则至少 1 次,可以多次匹配
只匹配前面的规则 0 次或 1 次。
有时候需要匹配一个跟在特定内容后面的或者在特定内容前面的字符串, Python 提供一个简便的前向界定和后向界定功能,或者叫前导指定和跟从指定功能。它们是:
括号中 ’…’ 代表你希望匹配的字符串的前面应该出现的字符串。
括号中的 ’…’ 代表你希望匹配的字符串后面应该出现的字符串。
1 >>> s=r’/* comment 1 */ code /* comment 2 */’ 2 >>> re.findall( r’(?<=//*).+?(?=/*/)’ , s ) 3 [‘ comment 1 ‘, ‘ comment 2 ‘] 4 5 >>> s = ‘aaa111aaa , bbb222 , 333ccc ‘ 6 >>> re.findall( r’(?<=[a-z]+)/d+(?=[a-z]+)‘ , s ) # 错误的用法 7 它会给出一个错误信息: 8 error: look-behind requires fixed-width pattern 9 10 >>> re.findall( r’/d+(?=[a-z]+)’, s ) 11 [‘111‘, ‘333‘]
只有当你希望的字符串前面不是’…’ 的内容时才匹配
只有当你希望的字符串后面不跟着 ’…’ 内容时才匹配。
最基本的组是由一对圆括号括起来的正则式。比如上面匹配包夹在字母中间的数字的例子中使用的 (/d+)
1 >>> s = ‘aaa111aaa , bbb222 , 333ccc ‘ 2 >>> re.findall (r‘[a-z]+(/d+)[a-z]+‘ , s ) 3 [‘111‘] 4 5 可以看到 findall 函数只返回了包含在 ’()’ 中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中。
‘(?P’ 代表这是一个 Python 的语法扩展 ’<…>’ 里面是你给这个组起的名字,比如你可以给一个全部由数字组成的组叫做 ’num’ ,它的形式就是 ’(?P<num>/d+)’ 。起了名字之后,我们就可以在后面的正则式中通过名字调用这个组,它的形式是 ‘(?P=name)’ 调用已匹配的命名组。要注意,再次调用的这个组是已被匹配的组,也就是说它里面的内容是和前面命名组里的内容是一样的。
1 我们可以看更多的例子:请注意下面这个字符串各子串的特点。 2 >>>s=‘aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg‘ 3 >>> re.findall( r‘([a-z]+)/d+([a-z]+)‘ , s ) # 找出中间夹有数字的字母 4 [(‘aaa‘, ‘aaa‘), (‘fff‘, ‘ggg‘)] 5 6 >>> re.findall( r ‘(?P<g1>[a-z]+)/d+(?P=g1)‘ , s ) # 找出被中间夹有数字的前后同样的字母 7 [‘aaa‘] 8 9 >>> re.findall( r‘[a-z]+(/d+)([a-z]+)‘ , s ) # 找出前面有字母引导,中间是数字,后面是字母的字符串中的中间的数字和后面的字母 10 [(‘111‘, ‘aaa‘), (‘777‘, ‘ggg‘)] 11 12 13 我们再看一个例子: 14 >>> s=‘111aaa222aaa111 , 333bbb444bb33‘ 15 >>> re.findall( r‘(/d+)([a-z]+)(/d+)(/2)(/1)‘ , s ) # 找出完全对称的 数字-字母-数字-字母-数字 中的数字和字母 16 [(‘111‘, ‘aaa‘, ‘222‘, ‘aaa‘, ‘111‘)]
例:
1 >>> s=‘111,222,aaa,bbb,ccc333,444ddd‘ 2 >>> rule=r’/b/d+/b’ 3 >>> compiled_rule=re.compile(rule) 4 >>> compiled_rule.findall(s) 5 [‘111‘, ‘222‘]
例:
1 >>> s= ‘Tom:9527 , Sharry:0003‘ 2 >>> m=re.match( r‘(?P<name>/w+):(?P<num>/d+)‘ , s ) 3 >>> m.group() 4 ‘Tom:9527‘ 5 6 >>> m.groups() 7 (‘Tom‘, ‘9527‘) 8 9 >>> m.group(‘name’) 10 ‘Tom‘ 11 12 >>> m.group(‘num’) 13 ‘9527‘
1 例,将下面字符串中的 ’dog’ 全部替换成 ’cat’ 2 >>> s=’ I have a dog , you have a dog , he have a dog ‘ 3 >>> re.sub( r’dog’ , ‘cat’ , s ) 4 ‘ I have a cat , you have a cat , he have a cat ‘ 5 6 如果我们只想替换前面两个,则 7 >>> re.sub( r’dog’ , ‘cat’ , s , 2 ) 8 ‘ I have a cat , you have a cat , he have a dog ‘ 9 10 或者我们想知道发生了多少次替换,则可以使用 subn 11 >>> re.subn( r’dog’ , ‘cat’ , s ) 12 (‘ I have a cat , you have a cat , he have a cat ‘, 3)
将一个正则式,使用 compile 函数编译,不仅是为了提高匹配的速度,同时还能使用一些附加的功能。编译后的结果生成一个 Pattern 对象,这个对象里面有很多函数,他们看起来和 re 模块的函数非常象,它同样有 findall , match , search ,finditer , sub , subn , split 这些函数,只不过它们的参数有些小小的不同。一般说来, re 模块函数的第一个参数,即正则规则不再需要了,应为规则就包含在 Pattern 对象中了,编译选项也不再需要了,因为已经被编译过了。因此 re 模块中函数的这两个参数的位置,就被后面的参数取代了。
findall , match , search 和 finditer 这几个函数的参数是一样的,除了少了规则和选项两个参数外,它们又加入了另外两个参数,它们是:查找开始位置和查找结束位置,也就是说,现在你可以指定查找的区间,除去你不感兴趣的区间。它们现在的参数形式是:
findall ( targetString [, startPos [,endPos] ] )
finditer ( targetString [, startPos [,endPos] ] )
match ( targetString [, startPos [,endPos] ] )
search ( targetString [, startPos [,endPos] ] )
正则式中的每个组都有一个序号,它是按定义时从左到右的顺序从 1 开始编号的。其实, re 的正则式还有一个 0 号组,它就是整个正则式本身。
我们来看个例子:
1 >>> p=re.compile( r’(?P<name>[a-z]+)/s+(?P<age>/d+)/s+(?P<tel>/d+).*’ , re.I ) 2 >>> p.groupindex 3 {‘age‘: 2, ‘tel‘: 3, ‘name‘: 1} 4 5 >>> s=’Tom 24 88888888 <=’ 6 >>> m=p.search(s) 7 >>> m.groups() # 看看匹配的各组的情况 8 (‘Tom‘, ‘24‘, ‘8888888‘) 9 10 >>> m.group(‘name’) # 使用组名获取匹配的字符串 11 ‘Tom’ 12 >>> m.group( 1 ) # 使用组序号获取匹配的字符串,同使用组名的效果一样 13 14 >>> m.group(0) # 0 组里面是什么呢? 15 ‘Tom 24 88888888 <=‘ 16 原来 0 组就是整个正则式 , 包括没有被包围到组里面的内容。当获取 0 组的时候,你可以不写这个参数。 m.group(0) 和 m.group() 的效果是一样的: 17 18 >>> m.group() 19 ‘Tom 24 88888888 <=‘
标签:是你 第一个 查找 fish com local 语言 除了 单词
原文地址:https://www.cnblogs.com/sunshine-blog/p/9803252.html