设为首页 收藏本站
查看: 3344|回复: 0

[经验分享] python内置模块[re]

[复制链接]

尚未签到

发表于 2018-8-8 08:33:48 | 显示全部楼层 |阅读模式
  https://www.cnblogs.com/dodoye/p/6218192.html 原
  python内置模块[re]
  re模块:
  python的re模块(Regular Expression正则表达式)提供各种正则表达式的匹配操作,在文本解析、复杂字符串分析和信息提取时是一个非常有用的工具。
  1、re的简介
  使用python的re模块,尽管不能满足所有复杂的匹配情况,但足够在绝大多数情况下能够有效地实现对复杂字符串的分析提取相关信息。python会将正则表达式转化为字节码,利用C语言的匹配引擎进行深度优先的匹配。
  import re
  print(re.doc)
  可以查询re模块的功能信息。
  2、re的正则表达式语法
  正则表达式的特殊字符:
  特殊字符    意义说明
DSC0000.jpg

DSC0001.jpg

  '$'演示:普通模式下,foo.$去搜索'foo1\nfoo2\n'只会找到'foo2′,但是在 MULTILINE 模式,还能找到 ‘foo1′,而且就用一个 $ 去搜索'foo\n'的话,会找到两个空的匹配:一个是最后的换行符,一个是字符串的结尾。如下演示:
  复制代码
  #'$'演示
  >> re.findall('(foo.$)', 'foo1\nfoo2\n')
  ['foo2']
  >> re.findall('(foo.$)', 'foo1\nfoo2\n')
  ['foo2']
  >> re.findall('(foo.$)', 'foo1\nfoo2\n', re.MULTILINE)
  ['foo1', 'foo2']
  >> re.findall('($)', 'foo\n')
  ['', '']
  复制代码
  *?, +?, ??演示:
  复制代码
  >> re.findall('<(.)>', '<H1>title</H1>')
  ['H1>title</H1']
  >> re.findall('<(.?)>', '<H1>title</H1>')
  ['H1', '/H1']
  >> re.search('<(.)>', '<H1>title</H1>').group()
  '<H1>title</H1>'
  >> re.search('<(.?)>', '<H1>title</H1>').group()
  '<H1>'
  复制代码
  (?...)演示:和指定了re.MULTILINE是一样的效果
  >> re.findall('(?m)(foo.$)', 'foo1\nfoo2\n')
  ['foo1', 'foo2']
  (?P<name>...)演示:
  复制代码
  >> m=re.match('(?P<var>[a-zA-Z_]\w)', 'abc=123')
  >> m.group('var') #通过var参数取值
  'abc'
  >> m.group(1)#通过数字取值
  'abc'
  >> re.match('<(?P<tagname>\w)>.</(?P=tagname)>', '<h1>xxx</h2>')  #这个不匹配
  >> re.match('<(?P<tagname>\w)>.*</(?P=tagname)>', '<h1>xxx</h1>')  #这个匹配
  <_sre.SRE_Match object; span=(0, 12), match='<h1>xxx</h1>'>
  复制代码
  (?<=...)演示:
  >> m = re.search('(?<=-)\w+', 'spam-egg')
  >> m.group(0)
  'egg'
  正则表达式特殊序列符号:
  特殊序列符号  意义说明
  \number 匹配number所指的组相同的字符串。组的序号从1开始。例如:(.+) \1可以匹配'the the'和'55 55',但不匹配'the end'。这种序列在一个正则表达式里最多可以有99个,如果number以0开头,或是有3位以上的数字,就会被当做八进制表示的字符了。同时,这个也不能用于方括号内。
  \A  只匹配字符串的开始。
  \b  匹配单词边界(包括开始和结束),这里的“单词”,是指连续的字母、数字和下划线组成的字符串。注意,\b的定义是\w和\W的交界,所以精确的定义有赖于UNICODE和LOCALE这两个标志位。
  \B  和\b相反,\B匹配非单词边界。也依赖于UNICODE和LOCALE这两个标志位。
  \d  相当于[0-9]
  \D  和\d相反。相当于[^0-9]
  \s  匹配任何空白字符,等效于[ \t\n\r\f\v]
  \S  和\s相反,匹配任意非空白字符:[^\t\n\r\r\v]
  \w  匹配任意数字和字母:[a-zA-Z0-9]
  \W  和\w相反,匹配任意非数字和字母:[^a-zA-Z0-9]
  \Z  只匹配字符串的结尾。
  3、re的主要模块功能函数:
  常用的功能函数包括:compile、search、match、split、findall(finditer)、sub(subn)、escape
  compile
  re.compile(pattern[, flags])
  作用:把正则表达式语法转化成正则表达式对象
  flags定义包括:
  re.I:忽略大小写
  re.L:表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
  re.M:多行模式
  re.S:’ . ’并且包括换行符在内的任意字符(注意:’ . ’不包括换行符)
  re.U: 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
  用了re.compile以后,正则对象会得到保留,这样在需要多次运用这个正则对象的时候,效率会有较大的提升。再用上面用过的例子来演示一下,用相同的正则匹配相同的字符串,执行100万次,就体现出compile的效率了。
  search
  re.search(pattern, string[, flags])
  search (string[, pos[, endpos]])
  作用:在字符串中查找匹配正则表达式模式的位置,返回 MatchObject 的实例,如果没有找到匹配的位置,则返回 None。
  match
  re.match(pattern, string[, flags])
  match(string[, pos[, endpos]])
  作用:match() 函数只在字符串的开始位置尝试匹配正则表达式,也就是只报告从位置 0 开始的匹配情况,而 search() 函数是扫描整个字符串来查找匹配。如果想要搜索整个字符串来寻找匹配,应当用 search()。
  复制代码
  #!/usr/bin/env python
  import re
  r1 = re.compile(r'world')
  if r1.match('helloworld'):
  print('match succeeds')
  else:
  print('match fails')
  if r1.search('helloworld'):
  print('search succeeds')
  else:
  print('search fails')
  复制代码
  说明一下:r是raw(原始)的意思。因为在表示字符串中有一些转义符,如表示回车'\n'。如果要表示\需要写为'\'。但如果我就是需要表示一个'\'+'n',不用r方式要写为:'\n'。但使用r方式则为r'\n'这样清晰多了。
  split
  re.split(pattern, string[, maxsplit=0, flags=0])
  split(string[, maxsplit=0])
  作用:可以将字符串匹配正则表达式的部分割开并返回一个列表。
  复制代码
  #简单IP分析
  #!/usr/bin/env python
  import re
  r1 = re.compile(r'\W+')
  print(r1.split(r'192.168.1.1'))
  print(re.split(r'(\W+)','192.168.1.1'))
  print(re.split(r'(\W+)','192.168.1.1',1))
  #输出结果为:
  ['192', '168', '1', '1']
  ['192', '.', '168', '.', '1', '.', '1']
  ['192', '.', '168.1.1']
  复制代码
  用匹配pattern的子串来分割string,如果pattern里使用了圆括号,那么被pattern匹配到的串也将作为返回值列表的一部分。如果maxsplit不为0,则最多被分割为maxsplit个子串,剩余部分将整个地被返回。
  >> re.split('\W+', 'Words, words, words.')
  ['Words', 'words', 'words', '']
  >> re.split('(\W+)', 'Words, words, words.')
  ['Words', ', ', 'words', ', ', 'words', '.', '']
  >> re.split('\W+', 'Words, words, words.', 1)
  ['Words', 'words, words.']
  如果正则有圆括号,并且可以匹配到字符串的开始位置的时候,返回值的第一项,会多出一个空字符串。匹配到字符结尾也是同样的道理:
  >> re.split('(\W+)', '...words, words...')
  ['', '...', 'words', ', ', 'words', '...', '']
  注意,split不会被零长度的正则所分割,将会报FureWarning警告,例如:
  >> re.split('x*', 'foo')
  C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32\lib\re.py:203:
  FutureWarning: split() requires a non-empty pattern match.
  return _compile(pattern, flags).split(string, maxsplit)
  ['foo']
  findall
  re.findall(pattern, string[, flags])
  findall(string[, pos[, endpos]])
  作用:在字符串中找到正则表达式所匹配的所有子串,并组成一个列表返回。
  复制代码
  #查找[]包括的内容(贪婪和非贪婪查找)
  #!/usr/bin/env python
  import re
  r1 = re.compile(r'([.])')
  print(re.findall(r1,&quot;hello[hi]heldfsdsf[iwonder]lo&quot;))
  r1 = re.compile(r'([.?])')
  print(re.findall(r1,&quot;hello[hi]heldfsdsf[iwonder]lo&quot;))
  print(re.findall(r'[0-9]{2}',&quot;fdskfj1323jfkdj&quot;))
  print(re.findall('([0-9][a-z])',&quot;fdskfj1323jfkdj&quot;))
  print(re.findall(r'(?=www)',&quot;afdsfwwwfkdjfsdfsdwww&quot;))
  print(re.findall(r'(?<=www)',&quot;afdsfwwwfkdjfsdfsdwww&quot;))
  #输入结果:
  []
  []
  ['13', '23']
  ['3j']
  ['', '']
  ['', '']
  复制代码
  #这个返回的就是元组的列表
  >> re.findall('(\d+).(\d+).(\d+).(\d+)', 'My IP is 192.168.0.2, and your is
  192.168.0.3.')
  [('192', '168', '0', '2'), ('192', '168', '0', '3')]
  finditer
  re.finditer(pattern, string[, flags])
  finditer(string[, pos[, endpos]])
  说明:和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并组成一个迭代器返回。
  >> for m in re.finditer('\w+', 'hello, world!'):
  ...     print(m.group())
  ...
  hello
  world
  sub
  re.sub(pattern, repl, string[, count, flags])
  sub(repl, string[, count=0])
  说明:在字符串 string 中找到匹配正则表达式 pattern 的所有子串,用另一个字符串 repl 进行替换。如果没有找到匹配 pattern 的串,则返回未被修改的 string。Repl 既可以是字符串也可以是一个函数。
  复制代码
  #!/usr/bin/env python
  import re
  p = re.compile('(one|two|three)')
  print(p.sub('num','one word two words three words apple',2))
  #输出结果:
  num word num words three words apple
  复制代码
  如果repl是个函数,每次pattern被匹配到的时候,都会被调用一次,传入一个匹配到的MatchObject对象,需要返回一个字符串,在匹配到的位置,就填入返回的字符串。
  >> def dashrepl(matchobj):
  ...     if matchobj.group(0) == '-': return ' '
  ...     else:return '-'
  >> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
  'pro--gram files'
  零长度的匹配也会被替换
  >> re.sub('x*', '-', 'abcxxd')
  '-a-b-c-d-'
  特殊地,在替换字符串里,如果有\g这样的写法,将匹配正则的命名组(前面介绍过的,(?P...)这样定义出来的东西)。\g这样的写法,也是数字的组,也就是说,\g<2>一般和\2是等效的,但是万一你要在\2后面紧接着写上字面意义的0,你就不能写成\20了(因为这代表第20个组),这时候必须写成\g<2>0,另外,\g<0>代表匹配到的整个子串。
  >> re.sub('-(\d+)-', '-\g<1>0\g<0>', 'a-11-b-22-c')
  'a-110-11-b-220-22-c'
  subn
  re.subn(pattern, repl, string[, count, flags])
  subn(repl, string[, count=0])
  说明:该函数的功能和 sub() 相同,只是它返回的是一个元组 (新字符串, 匹配到的次数)。
  >> re.subn('-(\d+)-', '-\g<1>0\g<0>', 'a-11-b-22-c')
  ('a-110-11-b-220-22-c', 2)
  escape
  把string中,除了字母和数字以外的字符,都加上反斜杆。
  >> print(re.escape('abc123@#$'))
  abc123\@#\$
  4、编译标志:
  标志  含义
  re.I,re.IGNORECASE  让正则表达式忽略大小写,这样一来,[A-Z]也可以匹配小写字母了。此特性和locale无关。
  re.L,re.LOCALE  让\w、\W、\b、\B、\s和\S依赖当前的locale。
  re.M,re.MULTILINE   影响'^'和'$'的行为,指定了以后,'^'会增加匹配每行的开始(也就是换行符后的位置);'$'会增加匹配每行的结束(也就是换行符前的位置)。
  re.S,re.DOTALL  影响'.'的行为,平时'.'匹配除换行符以外的所有字符,指定了本标志以后,也可以匹配换行符。
  re.U,re.UNICODE 让\w、\W、\b、\B、\d、\D、\s和\S依赖Unicode库。
  re.X,re.VERBOSE 运用这个标志,你可以写出可读性更好的正则表达式:除了在方括号内的和被反斜杠转义的以外的所有空白字符,都将被忽略,而且每行中,一个正常的井号后的所有字符也被忽略,这样就可以方便地在正则表达式内部写注释了。
  #下面两个正则表达式是等效的
  a = re.compile(r&quot;&quot;&quot;\d +  # the integral part
  .    # the decimal point
  \d   # some fractional digits&quot;&quot;&quot;, re.X)
  b = re.compile(r&quot;\d+.\d&quot;)
  5、方法/属性
  groups
  RE所含有的组的个数。
  groupindex
  一个mappingproxy字典,定义了命名组的名字和序号之间的关系。
  #这个正则有3个组,如果匹配到,第一个叫区号,最后一个叫分机号,中间的那个未命名
  >> pattern = re.compile(&quot;(?P<quhao>\d+)-(\d+)-(?P<fenjihao>\d+)&quot;)
  >> pattern.groups
  3
  >> pattern.groupindex
  mappingproxy({'fenjihao': 3, 'quhao': 1})
  pattern
  建立本RE的原始字符串,相当于源代码了,呵呵。
  >> pattern = re.compile(&quot;(?P<quhao>\d+)-(\d+)-(?P<fenjihao>\d+)&quot;)
  >> print(pattern.pattern)
  (?P<quhao>\d+)-(\d+)-(?P<fenjihao>\d+)
  group([group1, ...])
  返回一个或多个子组。如果参数为一个,就返回一个子串;如果参数有多个,就返回多个子串注册的元组。如果不传任何参数,效果和传入一个0一样,将返回整个匹配。如果某个groupN未匹配到,相应位置会返回None。如果某个groupN是负数或者大于group的总数,则会抛出IndexError异常。
  复制代码
  >> m = re.match(r&quot;(\w+) (\w+)&quot;, &quot;Isaac Newton, physicist&quot;)
  >> m.group(0) #整个匹配
  'Isaac Newton'
  >> m.group(1)#第一个子串
  'Isaac'
  >> m.group(2)#第二个子串
  'Newton'
  >> m.group(1,2) #多个子串组成元组
  ('Isaac', 'Newton')
  复制代码
  如果有其中有用(?P...)这种语法命名过的子串的话,相应的groupN也可以是名字字符串。
  >> m = re.match(r&quot;(?P<first_name>\w+) (?P<last_name>\w+)&quot;, &quot;Malcolm Reynolds&quot;)
  >> m.group('first_name')
  'Malcolm'
  >> m.group('last_name')
  'Reynolds'
  如果某个组被匹配到多次,那么只有最后一次的数据,可以被提取到
  >> m = re.match(r&quot;(..)+&quot;, &quot;a1b2c3&quot;)
  >> m.group(0)
  'a1b2c3'
  >> m.group(1)
  'c3'
  >> m.group(2)
  groups([default])
  返回一个由所有匹配到的子串组成的元组。default参数,用于给那些没有匹配到的组做默认值,它的默认值是None
  复制代码
  >> m = re.match(r&quot;(\d+).(\d+)&quot;, &quot;24.1632&quot;)
  >> m.groups()
  ('24', '1632')
  #default的作用
  >> m = re.match(r&quot;(\d+).?(\d+)?&quot;, &quot;24&quot;)
  >> m.groups() #第二个默认是None
  ('24', None)
  >> m.groups('0')#现在默认变成0
  ('24', '0')
  复制代码
  groupdict([default])
  返回一个包含所有命名组的名字和子串的字典,default参数,用于给那些没有匹配到的组做默认值,它的默认值是None
  >> m = re.match(r&quot;(?P<first_name>\w+) (?P<last_name>\w+)&quot;, &quot;Malcolm Reynolds&quot;)
  >> m.groupdict()
  {'first_name': 'Malcolm', 'last_name': 'Reynolds'}
  start([group]),end([group])
  返回的是:被组group匹配到的子串在原字符串中的位置。如果不指定group或group指定为0,则代表整个匹配。如果group未匹配到,则返回 -1。
  对于指定的m和g,m.group(g)和m.string[m.start(g):m.end(g)]等效。
  注意:如果group匹配到空字符串,m.start(group)和m.end(group)将相等
  复制代码
  >> m = re.search('b(c?)', 'cba')
  >> m.start(0)
  1
  >> m.end(0)
  2
  >> m.start(1)
  2
  >> m.end(1)
  2
  复制代码
  下面是一个把email地址里的“remove_this”去掉的例子
  >> email = &quot;tony@tiremove_thisger.net&quot;
  >> m = re.search(&quot;remove_this&quot;, email)

  >> email[:m.start()] + email[m.end():]'tony@tiger.net'

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-548433-1-1.html 上篇帖子: 编译安装Python3.6-Kavin.Qi的博客 下篇帖子: Python基础应用---类
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表