目录

  • 六、正则表达式基本知识

    • 6.1 字符匹配和字符长度匹配
    • 6.2 进阶
    • 6.3 re模块
    • 6.4 切分字符串
    • 6.5 分组
    • 6.6 贪婪分组
    • 6.7 编译(让匹配更加高效)
    • 6.8 小结
    • 6.9 正则表达式字符(仅仅用于查询)

六、正则表达式基本知识

字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦,而且代码难以复用。

正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。

所以我们判断一个字符串是否是合法的Email的方法是:

  1. 创建一个匹配Email的正则表达式;
  2. 用该正则表达式去匹配用户的输入来判断是否合法。

6.1 字符匹配和字符长度匹配

因为正则表达式也是用字符串表示的,所以,我们要首先了解如何用字符来描述字符。
在正则表达式中,如果直接给出字符,就是精确匹配。\d可以匹配一个数字,\w可以匹配一个字母或数字,所以:

  • 00\d'可以匹配'007',但无法匹配'00A'
  • '\d\d\d'可以匹配'010'
  • '\w\w\d'可以匹配'py3'

.可以匹配任意字符,所以:

  • 'py.'可以匹配'pyc''pyo''py!'等等。

要匹配变长的字符,在正则表达式中,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符:

来看一个复杂的例子:\d{3}\s+\d{3,8}

我们来从左到右解读一下:

  1. \d{3}表示匹配3个数字,例如'010'

  2. \s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格,例如匹配' '' '等;

  3. \d{3,8}表示3-8个数字,例如'1234567'

综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。

如果要匹配'010-12345'这样的号码呢?由于'-'是特殊字符,在正则表达式中,要用'\'转义,所以,上面的正则是\d{3}\-\d{3,8}

但是,仍然无法匹配'010 - 12345',因为带有空格。所以我们需要更复杂的匹配方式。\d{3}\s+\-\s+\d{3,8}

6.2 进阶

要做更精确地匹配,可以用[]表示范围,比如:

  • [0-9a-zA-Z\_]可以匹配一个数字、字母(大小写)或者下划线;

  • [0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100''0_Z''Py3000'等等;

  • [a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;

  • [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。

A|B可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'
^表示行的开头,^\d表示必须以数字开头。
$表示行的结束,\d$表示必须以数字结束。
你可能注意到了,py也可以匹配'python',但是加上^py$就变成了整行匹配,就只能匹配'py'了。

6.3 re模块

有了准备知识,我们就可以在Python中使用正则表达式了。Python提供re模块,包含所有正则表达式的功能。由于Python的字符串本身也用\转义,所以要特别注意:

s = 'ABC\\-001' # Python的字符串
# 对应的正则表达式字符串变成:
# 'ABC\-001'

因此我们强烈建议使用Python的r前缀,就不用考虑转义的问题了:

s = r'ABC\-001' # Python的字符串
# 对应的正则表达式字符串不变:
# 'ABC\-001'

先看看如何判断正则表达式是否匹配:

>>> import re
>>> re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
<_sre.SRE_Match object at 0x1026e18b8>
>>> re.match(r'^\d{3}\-\d{3,8}$', '010 12345')
>>>

match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None。常见的判断方法就是:

test = '用户输入的字符串'
if re.match(r'正则表达式', test):print 'ok'
else:print 'failed'

6.4 切分字符串

用正则表达式切分字符串比用固定的字符更灵活,请看正常的切分代码:

>>> 'a b   c'.split(' ')
['a', 'b', '', '', 'c']

嗯,无法识别连续的空格,用正则表达式试试:(很实用)

>>> re.split(r'\s+', 'a b   c')
['a', 'b', 'c']

无论多少个空格都可以正常分割。加入,试试:

>>> re.split(r'[\s\,]+', 'a,b, c  d')
['a', 'b', 'c', 'd']

再加入;试试:很牛,哈哈哈,以后会常用,要记住

>>> re.split(r'[\s\,\;]+', 'a,b;; c  d')
['a', 'b', 'c', 'd']

6.5 分组

分组也是相当重要,记住了
除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。比如:

^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:

>>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
>>> m
<_sre.SRE_Match object at 0x1026fb3e8>
>>> m.group(0)
'010-12345'
>>> m.group(1)
'010'
>>> m.group(2)
'12345'

如果正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来。
注意到group(0)永远是原始字符串, group(1)group(2) …… 表示第1、2、……个子串。

提取子串非常有用。来看一个更凶残的例子:

>>> t = '19:05:30'
>>> m = re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$', t)
>>> m.groups()
('19', '05', '30')

这个正则表达式可以直接识别合法的时间。但是有些时候,用正则表达式也无法做到完全验证,比如识别日期:

'^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$'

对于'2-30''4-31'这样的非法日期,用正则还是识别不了,或者说写出来非常困难,这时就需要程序配合识别了。

6.6 贪婪分组

最后需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的0

>>> re.match(r'^(\d+)(0*)$', '102300').groups()
('102300', '')

由于\d+采用贪婪匹配,直接把后面的0全部匹配了,结果0*只能匹配空字符串了。
必须让\d+采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0匹配出来,加个?就可以让\d+采用非贪婪匹配:

>>> re.match(r'^(\d+?)(0*)$', '102300').groups()
('1023', '00')

6.7 编译(让匹配更加高效)

当我们在Python中使用正则表达式时,re模块内部会干两件事情:

  1. 编译正则表达式,如果正则表达式的字符串本身不合法,会报错;

  2. 用编译后的正则表达式去匹配字符串。

如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配:

>>> import re
# 编译:
>>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
>>> re_telephone.match('010-12345').groups()
('010', '12345')
>>> re_telephone.match('010-8086').groups()
('010', '8086')

编译后生成Regular Expression对象,由于该对象自己包含了正则表达式,所以调用对象的方法时不用给出正则字符串。

6.8 小结

正则表达式非常强大,要在短短的一节里讲完是不可能的。要讲清楚正则的所有内容,可以写一本厚厚的书了。如果你经常遇到正则表达式的问题,你可能需要一本正则表达式的参考书。

请尝试写一个验证Email地址的正则表达式。版本一应该可以验证出类似的Email:

someone@gmail.com
bill.gates@microsoft.com

版本二可以验证并提取出带名字的Email地址:

<Tom Paris> tom@voyager.org

版本一

#-*- coding:utf-8 -*-
import rere_compile = re.compile(r'^\w+\@\w+\.\w+$')#re_compile = re.compile(r'^(\w+)@(\w+)(\.\[a-z]{3})$')    #出错,一个括号代表一个分组,错误不在@#re_compile = re.compile(r'^(\w+)@(\w+)(\.)(\[a-z]{3})$')    #出错,错误在第四个分组,[a-z]前不应该加转义符号\
re_compile2 = re.compile(r'^(\w+)@(\w+).([a-z]{3})$')
re_compile3 = re.compile(r'^(\w+)@([a-z]{2,10}).([a-z]{3})$')
re_compile4 = re.compile(r'^(\w+)@([a-z]{2,10}).([a-z]{3})$')
re_compile5 = re.compile(r'^(\w+)@([a-zA-Z]{2,10}).([a-zA-Z]{3})$')    #忽略大小写的匹配,注意要将a-z和A-Z放到一个中括号里面
re_compile6 = re.compile(r'^(\w*\.*\w+)@([a-zA-Z]{2,10}).([a-zA-Z]{3})$')    #这个能匹配bill.gates@microsoft.com,但是不能匹配someone@gmail.com
re_compile7 = re.compile(r'^(\w*\.*\w+)@([a-zA-Z]{2,10}).([a-zA-Z]{3})$')    #这个功能很强大,两个邮件都可以匹配
re_compile8 = re.compile(r'^(\w*\.*\w+)@([a-zA-Z]{2,10}).(\com)$')    #只能匹配尾缀为com的邮件email = 'someone@gmail.com'
email1 = 'bill.gates@microsoft.com'    #考验如何将'bill.gates'放入到一个分组中m = re_compile.match(email)
m1 = re_compile8.match(email1)
m.group(0)    #用于检测是否匹配成功
m.group(0)

版本二:

import reit = '<Tom Paris> tom@voyager.org'
item = re.spilt(r'[\>\s]')
re_compile = re.compile()

6.9 正则表达式字符(仅仅用于查询)

构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与运算符可以将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。

正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

6.9.1 普通字符

普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。
非打印字符
非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列:

字符 描述
\cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

6.9.2 特殊字符

所谓特殊字符,就是一些有特殊含义的字符,如上面说的 runoob 中的 ,简单的说就是表示任何字符串的意思。如果要查找字符串中的 * 符号,则需要对 * 进行转义,即在其前加一个 : runo*ob 匹配 runo*ob。

许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符 放在它们前面。

  • 下表列出了正则表达式中的特殊字符:
特别字符 描述
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 $。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。
* 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 *。
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。
. 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 . 。
[ 标记一个中括号表达式的开始。要匹配 [,请使用 [。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 ?。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\' 匹配 "",而 '(' 则匹配 "("。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 ^。
{ 标记限定符表达式的开始。要匹配 {,请使用 {。
竖号 指明两项之间的一个选择。要匹配 竖号,请使用 \竖号。

]

  • 上面竖号指代的是 '|'

限定符
限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m} 共6种。

  • 正则表达式的限定符有:
字符 描述
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

定位符
定位符使您能够将正则表达式固定到行首或行尾。它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。

定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。

  • 正则表达式的定位符有:
字符 描述
^ 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配。
$ 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。
\b 匹配一个字边界,即字与空格间的位置。
\B 非字边界匹配。

转载于:https://www.cnblogs.com/hugechuanqi/p/9609832.html

06.正则表达式基本知识相关推荐

  1. 万物之始正则表达式全解析三部曲(上篇)-正则表达式基础知识及语法

    前言 各位小伙伴大家好,接下来几天时间,我会从多个角度对正则表达式进行系统阐述,让你了解正则表达式的前世今生. 以下是博主整理的Linux知识专栏,喜欢的小伙伴可根据自己的需求自行订阅. Linux疑 ...

  2. 1023day5:class类属性方法、每次执行类属性+1、内建模块、时间装饰器wrapper、面向对象__slots__方法:限制类的属性等基础知识、正则表达式基础知识、多态鸭子类型

    文章目录 一.类class 1.Python类class 属性 方法 2.类的构造方法__init__() 3.每次执行一次类的属性+1 二.模块 1.内建模块 2.第三方模块 3.定义自己的模块 三 ...

  3. 正则环视 php,正则表达式基本知识(php)

    这里的知识点基本上是<正则指引>的读书笔记,只是每个知识点的示例代码用php来实现. 1. 字符组 字符组(Character Class)就是一组字符,在正则表达式中,它表示" ...

  4. 正则表达式基础知识---文本操作(尚学堂视频笔记)

    正则表达式(Regular Expression)基础知识 一.开发中使用流程: -分析要匹配的数据 写出测试用的典型数据 -在工具软件中进行匹配测试 -在程序中调用通过测试的正则表达式 (有些高级语 ...

  5. Perl正则表达式(1) - 正则表达式基础知识

    Perl正则表达式 1. 基础知识 Perl中正则表达式(regular expression)默认匹配 $_ 中的字符串,匹配成功就返回真,否则返回假: Perl匹配正则表达式时,可以使用变量内插, ...

  6. JavaScript正则表达式基础知识汇总

    一.创建正则对象: 1.构造函数RegExp创建正则对象 1 var pattern = new RegExp('s$'); //pattern匹配以s结尾的字符串 2.使用正则直接量 1 var p ...

  7. 正则表达式基础知识及应用(用于个人学习以及回顾)

    一. 正则表达式概述 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"). 正则表达式使用单 ...

  8. 正则表达式的知识普及

    为什么80%的码农都做不了架构师?>>>    1.什么事正则表达 正则表达式是可以匹配文本片段的模式.例如'python'可以用来匹配字符串'python'.你可以用这种匹配行为搜 ...

  9. 正则表达式基础知识,持续更新…

    两个网站 正则可视化 正则入门三十分钟 基本内容 定义 正则描述了一种字符串的匹配的模式 ,可以用来检查一个字符串是否包含某个子串或者是替换某个子串;一般用于表单验证,数据过滤,格式检查,数据采集,数 ...

最新文章

  1. 手抖把Python2.7卸载了,导致了自己的yum不可用
  2. mysql 分钟_mysql分钟到小时和分钟
  3. java双语试卷_Java程序设计基础(双语)试题题目及答案,课程2021最新期末考试题库,章节测验答案...
  4. GO SMS Pro App 被曝0day,泄露数百万条媒体消息
  5. matlab字符串中的换行符,如何在MATLAB中的子图中显示文本/字符串行?
  6. linux定时器与线程,Linux下的多线程定时器实现
  7. python导入mysql慢_如何更高、更快、更强地用python向mysql导入数据
  8. BOS系统的设计与实现
  9. kudu tablet的设计
  10. 关于电脑程序无响应的常见原因以及解决办法
  11. android 乐固渠道打包,安卓腾讯乐固(legutools)多渠道打包(友盟)
  12. Nature 曹云龙/谢晓亮等破解新冠病毒趋同进化机制,将为抗新冠病毒添新药!...
  13. 预告 | 将门三剑客直播夜话微软 Build 2017 开发者大会
  14. react组件的render方法
  15. 管理经济学【五】之 生产要素投入的决策分析
  16. 【黑金ZYNQ7000系列原创视频教程】07.自定义IPmdash;mdash;定制RTC IP实验
  17. 语音助手——QU——query纠错与改写
  18. MySQL狂神说笔记数据库笔记详解
  19. 经验分享:魅族手机刷机步骤
  20. Spark项目之电商用户行为分析大数据平台之(三)大数据集群的搭建

热门文章

  1. 挖掘机实现“无人驾驶”!协作机器人“魔法之手”取代人工操作
  2. Windows端5款MySQL客户端工具
  3. Python机器学习及分析工具:Scipy篇
  4. extern C的主要作用简单解释
  5. zblog php标签,201502200101 zblogphp调整“显示常用标签”个数方法
  6. 用matlab做单摆,单摆模型MATLAB程序
  7. 001_jQuery简介
  8. swapCursor vs changeCursor, what’s the difference?
  9. python列表中包含元祖_python列表与元祖
  10. jqprintsetup已经安装还会提示_英雄联盟PBE服务器安装指南 抢先体验新模式“云顶之弈”不用等...