正则

正则

概述:
正则表达式,Regular Expression,缩写regex、regexp、RE
正则表达式是文本处理极为重要的技术,用它可以对字符串按照某种规则进行检索、替换
1970年,Unix之父ken Thompson将正则表达式引入到Unix中文本编辑器ed和grep命令中,由此正则表达式普及开来
1980年后,perl语言对Henry Spencer编写的库,扩展了很多新的特性。1997年开始,Philip Hazel开发除了PCRE(perl compatible regular expressions),它被PHP和HTTPD等工具采用。
正则表达式应用极其广泛,shell中处理文本的命令、各种高级编程语言都支持正则
分类:
  • BRE:基本正则表达式,grep sed vi等软件支持。vim有扩展
  • ERE:扩展正则表达式,egrep(grep -E)、sed -r等
  • PCRE:几乎所有高级语言都是PCRE的方言或变种。python从1.6开始使用SRE正则表达式引擎,可以认为是PCRE的子集,见模块re

基本语法

元字符
  • . 匹配除换行符外任意一个字符
  • [abc]:字符集合,只能表示一个字符的位置,匹配所有包含的任意一个字符:[abc]匹配plain中的‘a’
  • [^abc]:字符集合,只能表示一个字符的位置,匹配除去集合内字符的任意一个字符:[abc]匹配plain中的‘p’、‘l’、‘i’、‘n’
  • [a-z]:字符范围,也是一个集合,表示一个字符位置,匹配所包含的任意一个字符
  • [^a-z]:匹配除去集合内字符的任意一个字符
  • \b:匹配单词的边界:\bb在文本中找到单词b开头的b字符
  • \B:不匹配单词的边界:t\B包含t的单词但是不以t结尾的t字符,如write
  • \d:[0-9]匹配一位数字
  • \D:[^0-9]匹配一位非数字
  • \s:匹配1位空白字符,包括换行符、制表符、空格
  • \S:匹配1位非空白字符
  • \w:匹配[a-zA-Z0-9_],包括中文的字
  • \W:匹配\w之外的字符
单行模式:
.可以匹配所有字符,包括换行符
^表示整个字符串的开头,正则行尾
^表示整个字符串的开始,$表示整个字符串的结尾。开始指的是\n后紧接着下一个字符,结束指的是/n前的字符
  • 转义:凡是在正则表达式中有特殊意义的符号,如果想使用它的本意,请使用\转义。反斜杠自身,则使用\。\r,\n还是转义后代表回车换行
重复
  • * :表示前面的正则表达式会重复0次或多次:e\w*单词中有e然后后面非空白字符
  • +:表示前面的正则表达式重复至少1次
  • ?:表示前面的正则表达式会重复0次或1次
  • {n}:重复固定n次
  • {n,}:重复至少n次 {1,}等价于+ | {0,}等价于啊* | {0,1}等价于?
  • {n,m}:重复n到m次
  • x|y:匹配x或者y
  • 捕获:
    • (pattern):使用小扩号指定一个子表达式,也叫分组。捕获后会自动分配组从1开始可以改变优先级
    • \数字:匹配对应分组
    • (?:pattern):如果仅仅为了改变优先级,就不需要捕获分组
    • (?\<name\>exp)、(?’name’exp):分组捕获,但是可以name访问分组python语法必须是(?P\<name\>exp)
  • 零宽断言
    • (?=exp):断言exp一定在匹配的右边出现,也就是说断言后面一定跟一个exp:f(?=oo)f后面一定有oo出现
    • (?<=exp):断言exp一定出现在匹配的左边,也就是说前面一定有个exp前缀:(?<=f)ood,ood前一定有f出现
  • 负向零宽断言:
    • (?!exp):断言exp一定不会出现在右侧,也就是说断言后面一定不是exp
    • (?>!exp):断言exp一定不能出现在左侧,也及时说断言前面一定不能是exp:(?<!f)ood ood的左边一定不是f</li>
  • (?#comment):注释 例如:f(?=oo)(?#这个后断言不捕获)
分组和捕获是同一个意思,能用简单表达式,就不要用复杂的表达式
贪婪与非贪婪
  • 默认是贪婪模式,也就是说尽量匹配更长的字符串
  • 非贪婪模式很简单,在重复的符号后面加一个?问好,就是尽量少匹配了
  • *?:匹配任意次,但尽可能少重复
  • +?:匹配至少一次,但尽可能少重复
  • ??:匹配0次或一次,但尽可能少重复
  • {n,}?:匹配至少n次,但尽可能少重复
  • {n,m}?:匹配至少n次,至多m次,但尽可能少重复
  • 引擎选项:
  • IgnoreCase:匹配时忽略大小写。re.l/re.IGNORECASE
  • Singleline:单行模式:.可以匹配所有字符,包括\n。re.S/re.DOTALL
  • Multiline:多行模式:^行首、$行尾。re.M/re.MULTILINE
  • IgnorePatternWhitespace:忽略表达式中的空白字符,如果要使用空白字符用转义,#可以用来左注释。re.X/re.VERBOSE
练习:
匹配身份证号:
\d{10}[0-9]{2}([0-2]\d|3[01])\d{3}(\d|x)
Python的正则表达式
  • Python使用re模块提供了正则表达式处理的能力
  • 常量:
    • re.M/re.MULTLINE:多行模式
    • re.S/re.DOTALL:单行模式
    • re.l/re.IGNORECASE:忽略大小写
    • re.X/re.VERBOSE:忽略表达式中的空白字符
    • 使用|位或运算开启多种选项
  • 方法:
    • 编译:
      • re.compile(pattern,flags=0)
      • 设定flags,编译模式,返回正则表达式对象regex
      • pattern就是正则表达式字符串,flags是选项。正则表达式需要被编译,为了提高效率,这些编译后的结果被保存,下次使用同样的pattern的时候,就不需要再次编译。
      • re的其他方法为了提高效率都调用了编译方法,就是为了提速
        单次匹配:
    • re.match(pattern,string,flags=0)
    • regex.match(string,pos[,endpos])
    • match匹配从字符串的开头匹配,regex对象match方法可以重设定开始位置和结束位置。返回match对象
    • re.search(pattern,string,flags=0)
    • regex.search(string[,pos[,endpos]])
    • 从头搜索直到第一个匹配,regex对象search方法可以重设定开始位置和结束位置,返回match对象
    • re.fullmatch(pattern,string,flags=0)
    • regex.fullmatch(string[,pos[,endpos]])
    • 整个字符串和正则表达式匹配
全部匹配
* re.findall(pattren,string,flag=0)
* regex.findall(string[,pos[,endpos]])
* 对整个字符串,从左至右匹配,返回所有匹配项的列表
* re.finditer(pattern,string,flag=0)
* regex.finditer(string[,pos[,endpos]])
* 对整个字符串,从左至右匹配,返回所有匹配项,返回`迭代器`
* 注意:每次迭代返回的是match对象
#举例:
In [43]: s = ”’bottle\nbag\nbig\napple”’
In [44]: for x in enumerate(s):
…: if x[0] % 8 == 0:
…: print()
…: print(x,end=”)
…: print(‘\n’)
(0, ‘b’)
(8, ‘a’)
(16, ‘p’)
In [45]: result = re.match(‘b’,s)#找不到第一个就不找了
In [46]: print(1,result)
1 <_sre.SRE_Match object; span=(0, 1), match=’b’>
In [47]: result = re.match(‘a’,s)#第一个没找到就返回None
In [48]: print(2,result)
2 None
In [49]: result = re.match(‘^a’,s,re.M)#依然从头找
In [50]: print(3,result)
3 None
In [51]: result = re.match(‘^a’,s,re.S)
In [52]: print(4,result)
4 None
#先编译,然后使用正则表达式对象
In [53]: regex = re.compile(‘a’)
In [54]: result = regex.match(s)
In [55]: print(5,result)
5 None
In [56]: result = regex.match(s,15)#把索引15作为开始找
In [57]: print(6,result)
6 <_sre.SRE_Match object; span=(15, 16), match=’a’>
#search方法
In [3]: s
Out[3]: ‘bottle\nbig\nbag\napple’
In [4]: re.search(‘^b’,s)#扫描找到匹配的第一个位置
Out[4]: <_sre.SRE_Match object; span=(0, 1), match=’b’>
In [6]: re.search(‘^b\w+’,s)
Out[6]: <_sre.SRE_Match object; span=(0, 6), match=’bottle’>
In [7]: re.search(‘^b\w+’,s,re.M)
Out[7]: <_sre.SRE_Match object; span=(0, 6), match=’bottle’>
In [9]: result = re.compile(‘^b’,re.M)#提前编译好再调用
In [10]: result.search(s)
Out[10]: <_sre.SRE_Match object; span=(0, 1), match=’b’>
In [11]: result.search(s,10,20)#提前编译的可以使用pos,endpos
Out[11]: <_sre.SRE_Match object; span=(11, 12), match=’b’>
#fullmatch方法
In [12]: re.fullmatch(‘bag’,s)
In [13]: result = re.compile(‘bag’,re.M)
In [14]: result.fullmatch(s,7,10)#无返匹配结果
In [15]: s
Out[15]: ‘bottle\nbig\nbag\napple’
In [18]: result.fullmatch(s,11,14)#指定索引位置,要完全匹配,多少都不行。末尾是开区间
Out[18]: <_sre.SRE_Match object; span=(11, 14), match=’bag’>
#findall方法,全部匹配
In [19]: re.findall(‘^b’,s)#单行模式下,此处^不是词首而是行首的意思
Out[19]: [‘b’]
In [20]: s
Out[20]: ‘bottle\nbig\nbag\napple’
In [21]: re.findall(‘^b’,s,re.M)#多行模式可以返回所有b开头的行
Out[21]: [‘b’, ‘b’, ‘b’]
In [66]: re.findall(r’\bb\w+\b’,s)#单行模式匹配行中的多个单词
Out[66]: [‘bottle’, ‘bag’, ‘big’]
In [64]: re.findall(‘b\w+’,s)
Out[64]: [‘bottle’, ‘bag’, ‘big’]
#finditer方法,全部匹配并返回生成器对象
In [68]: c = re.finditer(‘b\w+’,s)
In [69]: print(next(c))
<_sre.SRE_Match object; span=(0, 6), match=’bottle’>
In [70]: print(next(c))
<_sre.SRE_Match object; span=(7, 10), match=’bag’>
In [71]: print(next(c))
<_sre.SRE_Match object; span=(11, 14), match=’big’>
匹配替换
  • re.sub(pattern,replacement,string,count=0,flags=0)
  • regex.sub(replacement,string,count=0)
  • 使用pattern对字符串string进行匹配,对匹配项使用repl替换
  • replacement可以是string、bytes、function
  • re.subn(pattern,replacement,string,count=0,flags=0)
  • regex.subn(replacement,string,count=0)
  • 同sub返回一个元组(new_string,number_of_sub_made)
#sub举例:
In [79]: s
Out[79]: ‘bottle bag big apple’
In [76]: re.sub(‘a’,’c’,s)
Out[76]: ‘bottle bcg big cpple’
In [77]: regex = re.compile(‘e’)
In [80]: regex.sub(‘mage’,s)
Out[80]: ‘bottlmage bag big applmage
#subn举例:
In [82]: re.subn(‘b’,’Thunk’,s)
Out[82]: (‘Thunkottle Thunkag Thunkig apple’, 3)#返回元组及替换次数
字符串分割
字符串分割函数劣势:不能指定多个字符串进行分割
  • re.split(pattern,string,maxsplit=0,flags=0)
  • re.split分割字符串
In [114]: s
Out[114]: ‘bottle \n ba|g \nbig’
In [115]: print(s.split())#字符串切割函数无法做到多分隔符分割
[‘bottle’, ‘ba|g’, ‘big’]
In [120]: re.split(‘[\se]’,s,re.M)#通过正则指定多分割符切割
Out[120]: [‘bottl’, ”, ”, ”, ‘ba|g’, ”, ‘big’]
In [121]: re.split(‘[\sb]’,s,re.M)
Out[121]: [”, ‘ottle’, ”, ”, ”, ‘a|g’, ”, ”, ‘ig’]
分组
  • 使用小扩号的pattrn捕获的数据被放到了组group中
  • match、search函数可以返回match对象;findall返回字符串列表;finditer返回一个个match对象
  • 如果pattern中使用了分组,如果有匹配结果,会在match对象中
  • 1.使用group(N)方式返回对应分组,1-N是对应的分组,0返回整个匹配的字符串
  • 2.如果使用了命名分组,可以使用group(‘name’)的方式取分组
  • 3.也可以使用groups()返回所有分组
  • 4.使用groupdict()返回所有命名的分组
#group分组
In [137]: regex = re.compile(‘(b\w+)’)
In [138]: regex.match(s)
Out[138]: <_sre.SRE_Match object; span=(0, 6), match=’bottle’>
In [148]: regex.search(s).groups()#groups取出所有分组并返回元组
Out[148]: (‘bottle’,)
In [149]: regex.search(s).group()
Out[149]: ‘bottle’
In [152]: regex = re.compile(‘(b\w+)\s(?P<name2>b\w+)’)#定义分组名称
In [153]: regex.search(s).group()
Out[153]: ‘bottle\nbag’
In [154]: regex.search(s).groups()
Out[154]: (‘bottle’, ‘bag’)
In [157]: regex.search(s).group(‘name2’)#调取名称分组
Out[157]: ‘bag’
In [158]: regex.search(s).group(1)#索引分组
Out[158]: ‘bottle’
In [159]: regex.search(s).groupdict()#将分组转换成字典
Out[159]: {‘name2’: ‘bag’}
#迭代:
In [167]: for x in result:
…: print(type(x),x,x.group(),x.group(‘name2’))
—————————————————————————
TypeError Traceback (most recent call last)
<ipython-input-167-2b12e049a45a> in <module>()
—-> 1 for x in result:
2 print(type(x),x,x.group(),x.group(‘name2’))
TypeError: ‘_sre.SRE_Match’ object is not iterable#match对象不可迭代
In [168]: type(result)
Out[168]: _sre.SRE_Match
In [169]: regex = re.compile(‘(?P<head>b\w+)’)
In [170]: result = regex.finditer(s)#生成一个可迭代对象
In [171]: for x in result:
…: print(type(x),x,x.group(),x.group(‘head’))
<class ‘_sre.SRE_Match’> <_sre.SRE_Match object; span=(0, 6), match=’bottle’> bottle bottle
<class ‘_sre.SRE_Match’> <_sre.SRE_Match object; span=(7, 10), match=’bag’> bag bag
<class ‘_sre.SRE_Match’> <_sre.SRE_Match object; span=(11, 14), match=’big’> big big
作业:(红色标记未完成)
1.匹配邮箱地址,正确的
test@hot-mail.com
v-ip@magedu.com
web.manager@magedu.com.cn
super.user@google.com
a@w-a-com
[\w-]+@[\w-]+\.\w+ #没有匹配w-a-com的那条
test@hot-mail.com
v-ip@magedu.com
manager@magedu.com
user@google.com
2.匹配html标记的内容
<\w\s\w+=\'(?<url>[^’]+)\’\s\w+=\'(?<target>[^’]+)\’>(?<name>\w+)
http://www.magedu.com/index.html’ target=’_blank’>马哥教育
3.判断密码强弱
要求密码必须由10-15位,指定字符串组成:
* 十进制
* 大写字母
* 小写字母
* 下划线
* 要求四种类型的字符串都要出现才算合法的强密码
*
思路:Alt text
4.单词统计word count,对samplt.txt进行单词统计,要求使用正则
代码:Alt text

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/88239

(0)
Thunk_LeeThunk_Lee
上一篇 2017-11-05 23:38
下一篇 2017-11-06 19:37

相关推荐

  • Linux小工具之cheat

    随着linux学习的深入,接触到的命令越来越多,此时,考验脑力的时候就到了,除非你是”脑王”,否则面对多如牛毛的linux命令,真的会崩溃!linux前辈们貌似也被同样的问题所困扰,所以,他们发明了cheat。cheat是在GNU通用公共许可证下,为Linux命令行用户发行的交互式备忘单应用程序。它提供显示Linux命令使用案例,包括该命令所有的选项和简短但…

    2017-08-10
  • 新的学期,新的开始:新的起点,新的终点!

    马哥教育Linux面授30期,

    2018-03-26
  • sed命令用法详解

    1.sed运行原理         sed(stream editor)是一个行处理器。处理时,把当前处理的行放到“模式空间中”,处理完毕后,把该行输出到屏幕,接着处理下一行;这样不断重复,直到末行;此时文件本身内容并没有改变 2.sed用途    …

    Linux干货 2016-08-15
  • lvs集群搭建

    Linux Cluster: Cluster:计算机集合,为解决某个特定问题组合起来形成的单个系统; Linux Cluster类型:LB:Load Balancing,负载均衡;HA:High Availiablity,高可用;A=MTBF/(MTBF+MTTR)(0,1):90%, 95%, 99%, 99.5%,  99.9%, 99.99%…

    2017-05-09
  • OpenSSH的应用和利用OpenSSL创建私有CA签证给httpd服务器开起https

    一、OpenSSH     OpenSSH与SSH协议是远程登录的首选连接工具。它加密所有流量,以消除窃听,连接劫持和其它攻击。OpenSSH常常被误认以为与OpenSSL有关系,但实际上这两个项目的有不同的目的,不同的发展团队,名称相近只是因为两者有同样的软件发展目标──提供开放源代码的加密通讯软件。  &…

    Linux干货 2016-04-24
  • Linux进程管理常用命令(二)

       htop命令:         选项:         -d # : 指定延迟时间间隔;         -u  UserName :仅显示指定用户的进程;       &n…

    Linux干货 2017-01-05

评论列表(1条)

  • 逆神阳
    逆神阳 2017-11-06 20:27

    朋友,你看的是多少期的内容?怎么会有这么多的知识呢?