常用缩写字符及其含义表格查询

缩写字符分类 含义
\d 0-9的任意数字
\D 除0-9的数字以外的任何字符
\w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
\W 除字母、数字和下划线意外的任何字符
\s 空格、制表符或换行符(可以认为是匹配“空白”字符)
\S 除空格、制表符或换行符的任何字符
? 问号紧跟于分组后表示前面分组的内容是可有可无的
* 星号紧跟于分组后表示前面分组的内容匹配0次或多次
+ 加号紧跟于分组后表示前面分组的内容匹配至少1次
| 管道匹配多个分组
{} 花括号内加数字表示匹配特定字数
. 句点表示匹配任何字符(除了换行)

在Python中使用正则表达式的步骤

在Python中使用正则表达式主要有下面几个步骤:

  1. import re导入正则表达式模块;
  2. re.compile()函数创建一个Regex 对象;
  3. 向Regex 对象的search()findall()方法传入目标字符串;
  4. 调用Matches 对象的group()方法,返回实际匹配文本的字符串。

Python正则表达式详细说明

通过在字符串的第一个引号之前加r来向re.compile()传递原始字符串

Python中转义字符使用倒斜杠"\"。假如我们需要打印出"\n",则需要输入转义字符\\,才能打印出一个倒斜杠。所以"\\n"表示一个倒斜杠加上一个小写的n。但是,通过在字符串的第一个引号之前加上r,可以将该字符串标记为原始字符串,它不包括转义字符。

利用括号分组

假如我们想要匹配下面文本中的电话号码,并且将区号从中分离。则我们可以添加括号在正则表达式中创建“分组”:(\d\d\d)-(\d\d\d\d\d\d\d\d)。然后使用group()匹配对象方法,从第二个分组中获取需要的文本。正则表达式字符串中的第一对括号是第一组,第二对括号是第二组。向group()匹配对象方法传入整数1或2,就可以取得匹配文本的不同部分。向group()方法传入0或不传参数,将返回整个匹配的文本,groups() 方法可以一次获取所有的分组。(注意groups()和group(0)的差异)例如:

>>> import re
>>> phoneNumRegex = re.compile(r"(\d\d\d)-(\d\d\d\d\d\d\d\d)")
>>> mo = phoneNumRegex.search("My number is 029-88888888. ")
>>> mo.group(1)
'029'
>>> mo.group(2)
'88888888'
>>> mo.group(0)
'029-88888888'
>>> mo.group()
'029-88888888'
>>> mo.groups()
('029', '88888888')

用管道匹配多个分组

字符“|”称为“管道”。希望匹配许多表达式中的一个时,就可以使用它。例如,正则表达式r"Kitty|Tiny"将匹配“Kitty”或“Tiny”。如果二者都在文本中,则第一个出现的将作为Match对象返回。例如:

>>> nameRegex = re.compile(r"Kitty|Tiny")
>>> mo1 = nameRegex.search("Tiny and Rose and Kitty. ")
>>> mo1.group()
'Tiny'

假如我们希望匹配Batman、Batwoman、Batcar、Batmobile中的任意一个,因为这些单词都是以Bat开始,所以如果只指定一次前缀就会很方便。例如:

>>> nameRegex_2 = re.compile(r"Bat(man|woman|car|mobile)")
>>> mo2 = nameRegex_2.search("Batt、Batmobile、Batwoman、Batcar、Batman")
>>> mo2.group()
'Batmobile'
>>> mo2.group(1)
'mobile'

问号紧跟于分组后表示前面分组的内容是可有可无的

例如在匹配电话号码的例子中,假如遇到没有区号的电话号码,前面例子中的代码是无法匹配的,我们可以通过在分组后加问号来解决。例如:

>>> phoneNumRegex_2 = re.compile(r"(\d\d\d-)?(\d\d\d\d\d\d\d\d)")
>>> mo = phoneNumRegex_2.search("My phone number is 12356897. ")
>>> mo.group()
'12356897'

星号紧跟于分组后表示前面分组的内容匹配0次或多次

简单,不用解释,例如:

>>> emRegex = re.compile(r"e(m)*")
>>> mo = emRegex.search("emmmmmmmmmmm fuck trump. ")
>>> mo.group()
'emmmmmmmmmmm'

加号紧跟于分组后表示前面分组的内容匹配至少1次

简单,不用解释,例如:

>>> emRegex = re.compile(r"e(m)+")
>>> mo = emRegex.search("e fuck trump. ")
>>> mo.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group' # 没找到
>>> mo = emRegex.search("em fuck trump. ")
>>> mo.group()
'em'

用花括号匹配特定次数

如果想要查找一个分组重复特定次数的文本,则在该分组后紧跟一个花括号,其中的数字表示重复的次数。例如:(ha){3}匹配字符串“hahaha”,(ha){1,3}匹配字符串“ha”、“haha”或“hahaha”。这个花括号里面的规则和数组切片的那个规则是一样的,如{3,}将匹配3次及以上实例;{,5}将匹配0到5次实例。例如:

>>> haRegex = re.compile(r"(ha){1,}")
>>> mo = haRegex.search("hahahahahahahahahahah. ")
>>> mo.group()
'hahahahahahahahahaha'

.*来匹配除了换行符之外的任意多个字符

.可以匹配任意字符(除了换行符),*表示之前分组重复0及以上次数。则.*组合可以匹配任意字符串(除换行符)。

贪心和非贪心匹配

在前面的例子中,(ha){1,}可以匹配1个或其他数量个ha,但为什么会返回最长的。这是因为Python的正则表达式默认是贪心的,这表示在有二义的情况下,他们匹配最长的字符串。要想让他返回最短的那个,即将他变成非贪心的,则需要在花括号后加一个问号,这里注意区别前述中分组后加问号是表示可有可无的意思。例如:

>>> haRegex = re.compile(r"(ha){1,}?")
>>> mo = haRegex.search("hahahahahahahahahahah. ")
>>> mo.group()
'ha'

search()方法返回第一个匹配到的对象,findall()方法返回所有匹配到的字符串

search()方法返回一个Match对象,这个对象拥有group()方法;findall()方法直接返回一个列表,而列表则没有group()方法。如下:

>>> import re
>>> phoneNumRegex = re.compile(r"(\d\d\d-)?(\d\d\d\d\d\d\d\d)")
>>> mo = phoneNumRegex.search("Home: 029-88618871, Office: 010-36758954. ")
>>> mo
<_sre.SRE_Match object; span=(6, 18), match='029-88618871'>
>>> mo.group()
'029-88618871'
>>> mo_2 = phoneNumRegex.findall("Home: 029-88618871, Office: 010-36758954. ")
>>> mo_2
[('029-', '88618871'), ('010-', '36758954')]
>>> mo_2.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'group'

总结:

  1. 如果调用在一个没有分组的正则表达式上,例如\d\d\d-\d\d\d\d\d\d\d\d,方法findall()将返回一个匹配字符串的列表,例如['029-88618871','010-36758954'];
  2. 如果调用在一个有分组的正则表达式上,例如(\d\d\d-)?(\d\d\d\d\d\d\d\d),方法findall()将返回一个字符串的元组的列表,每个分组对应元组中的一个字符串,例如:[('029-', '88618871'), ('010-', '36758954')]。

建立自己的字符分类

如果觉得想要匹配的字符由上面的缩写(\s\d\w等)来表示太宽泛,可以用方括号定义自己的字符分类。如[abcdeABCDE]或[a-eA-E]将匹配“abcdeABCDE”中的任意字符一次。值得注意的是,方括号中普通的正则表达式符号不会被解释,这就意味着在匹配"."时不需要输入"\."等。

通过在左方括号后紧跟一个字符,就可以得到“非字符类”。如[a-eA-E]就匹配所有除了“abcdeABCDE”以外的任意字符一次。

插入字符和美元字符

在正则表达式的开始处使用插入符号(^),表明匹配必须发生在被查找文本的开始除。类似的,在正则表达式的末尾加上美元符号($),表示该字符串必须以这个正则表达式的模式结束才可以匹配到。二者可以同时使用。例如:

helloRegex = re.compile(r"^hello")
>>> mo = helloRegex.search("oh, hello!")
>>> mo_2 = helloRegex.search("hello, Kitty.")
>>> mo == None
True
>>> mo_2
<_sre.SRE_Match object; span=(0, 5), match='hello'>

使用sub()方法替换字符串

正则表达式不仅能够找到字符串,还能够捎带着替代找到的字符串,Regex对象的sub()方法需要传入两个字符串参数。第一个参数用来取代查找到的字符串,第二个参数为要查找的字符串。例如:

>>> findXiamenRegex = re.compile(r"Xiamen")
>>> findXiamenRegex.sub("Xi'an", "Xiamen is the capital of Shaanxi.")
"Xi'an is the capital of Shaanxi."

通过传入re.IGNORECASEre.DOTALLre.VERBOSE来忽略大小写、匹配换行符和多行输入正则表达式

re.compile()中传入re.IGNORECASE或re.I参数可以在匹配时忽略大小写;传入re.DOTALL参数来使句点能够匹配换行符;传入re.VERBOSE来进行复杂正则表达式的多行输入。

re.compile()不支持同时传入多个以上的3个参数,我们可以使用管道符号"|"来进行多个参数的传入。例如re.compile(r"fool", re.I|re.DOTALL|re.VERBOSE)

小项目:提取剪贴板中的手机号码、座机号码和邮件地址,并转换为规范格式并重新写回剪贴板(做完就啥都懂了)

这个项目可以分为以下几步:

  1. 从剪贴板取得文本;
  2. 找出文本中所有的手机号码、座机号码和邮件地址;
  3. 将它们粘贴回剪贴板。

首先我们通过网络搜索得知,国内座机号码区号位3-4位,且均位0开头;国内手机号码则都是1开头的,有的可能含有86或+86前缀。

代码如下:

#! python3
# phoneAndEmail.py - Finds phone numbers and email addresses on the clipboard. import pyperclip
import re # create phone number regex phone1_Regex = re.compile(r'''(
(\+)?
(86)?
(1\d{2})
(-|\s)?
(\d{8})
(\D)
)''', re.VERBOSE) phone2_Regex = re.compile(r'''(
(0\d{2,3})?
[-]?
(\d{8})
(\-\d{1,4})?
)''', re.VERBOSE) # create email regex
emailRegex = re.compile(r'''(
[a-zA-Z0-9._%+-]+
@
[a-zA-Z0-9.-]+
)''', re.VERBOSE) # Find matches in clipboard text.
text = str(pyperclip.paste())
matches = [] for groups in phone1_Regex.findall(text):
phoneNum = groups[3] + groups[5]
matches.append(phoneNum) for groups in phone2_Regex.findall(text):
phoneNum = groups[1] + groups[2]
if groups[3] is not None:
phoneNum += groups[3]
matches.append(phoneNum) for groups in emailRegex.findall(text):
matches.append(str(groups)) # Copy results to the clipboard.
if len(matches) > 0:
pyperclip.copy("\n".join(matches))
print("Copied to clipboard: ")
print("\n".join(matches))
else:
print("No phone numbers or email address found. ")

复制一段含有手机号码和电子邮件地址的文本,然后运行程序试试吧。

更多Python正则表达式

更多Python正则表达式内容见:官方文档

[Python学习笔记]系列是我在学习《Python编程快速上手——让繁琐工作自动化(Automate The Boring Stuff With Python)》这本书时的学习笔记。通过自己再手敲一遍概念和代码,方便自己记忆和日后查阅。如果对你有帮助,那就更好了!

[Python学习笔记]正则表达式总结的更多相关文章

  1. Python学习笔记——正则表达式入门

    # 本文对正则知识不做详细解释,仅作入门级的正则知识目录. 正则表达式的强大早有耳闻,大一时参加一次选拔考试,题目就是用做个HTML解析器,正则的优势表现得淋漓尽致.题外话不多讲,直接上干货: 1. ...

  2. python学习笔记----正则表达式

    正则: regular expression 常用的场景: #正则的包 >>> import re #match:开头匹配,匹配到,返回一个匹配对象,否则返回None >> ...

  3. python学习笔记——正则表达式regex

    1 概述 1.1 定义 本质是由一系列字符和特殊符号组成的字串,用来表示一定规则的某一类字符串. 1.2 特点 正则表达式是一个独立的技术,其在多种编程语言中使用. 在python语言中的正则表达式模 ...

  4. Python学习笔记——正则表达式

    今天把之前学的正则表达式好好总结总结. 一.元字符 . :  .表示可以匹配任意一个字符 \d  :  \d表示可以匹配任意一个数字 \D  : \D表示可以匹配任意一个非数字 \s  :  \s表示 ...

  5. Python学习笔记基础篇——总览

    Python初识与简介[开篇] Python学习笔记——基础篇[第一周]——变量与赋值.用户交互.条件判断.循环控制.数据类型.文本操作 Python学习笔记——基础篇[第二周]——解释器.字符串.列 ...

  6. Python学习笔记(十一)

    Python学习笔记(十一): 生成器,迭代器回顾 模块 作业-计算器 1. 生成器,迭代器回顾 1. 列表生成式:[x for x in range(10)] 2. 生成器 (generator o ...

  7. Python学习笔记,day5

    Python学习笔记,day5 一.time & datetime模块 import本质为将要导入的模块,先解释一遍 #_*_coding:utf-8_*_ __author__ = 'Ale ...

  8. 【目录】Python学习笔记

    目录:Python学习笔记 目标:坚持每天学习,每周一篇博文 1. Python学习笔记 - day1 - 概述及安装 2.Python学习笔记 - day2 - PyCharm的基本使用 3.Pyt ...

  9. Python 学习笔记(上)

    Python 学习笔记(上) 这份笔记是我在系统地学习python时记录的,它不能算是一份完整的参考,但里面大都是我觉得比较重要的地方. 目录 Python 学习笔记(上) 基础知识 基本输入输出 模 ...

随机推荐

  1. Redis集群搭建,伪分布式集群,即一台服务器6个redis节点

    Redis集群搭建,伪分布式集群,即一台服务器6个redis节点 一.Redis Cluster(Redis集群)简介 集群搭建需要的环境 二.搭建集群 2.1Redis的安装 2.2搭建6台redi ...

  2. SpringBoot启动方式,Spring Boot 定义系统启动任务

    SpringBoot启动方式,Spring Boot 定义系统启动任务 SpringBoot启动方式 1.1 方法一 1.2 方法二 1.2.1 start.sh 1.2.2 stop.sh 1.2. ...

  3. 根据pom标签修改

    sed -i "s/<count>1<\/count>/<count>2<\/count>/g"  pom.xml

  4. Spring cloud-Bus (消息总线)

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring ...

  5. Spring boot 集成MQ

    import lombok.extern.java.Log; import org.springframework.amqp.core.TopicExchange; import org.spring ...

  6. JavaWeb-tomcat安装(Unsupported major.minor version 51.0/startup.bat闪退)

    JavaWeb-tomcat安装(Unsupported major.minor version 51.0) 一 启动startup.bat 出错i 今天安装tomcat出错,折腾了一下午,收获了许多 ...

  7. oss-server 小型对象存储系统

    oss-server 项目介绍 oss-server是针对项目开发时提供的小型对象存储系统,开发者在针对文件上传时业务剥离,同时方便文件迁移,为满足单个项目,多个系统的情况下,提供统一的oss服务 o ...

  8. Codeforces #620 div2 B

    题目: Returning back to problem solving, Gildong is now studying about palindromes. He learned that a  ...

  9. 用了很多年Dubbo,连Dubbo线程池监控都不知道,觉得自己很厉害?

    前言 micrometer中自带了很多其他框架的指标信息,可以很方便的通过prometheus进行采集和监控,常用的有JVM的信息,Http请求的信息,Tomcat线程的信息等. 对于一些比较活跃的框 ...

  10. 踏上Revit二次开发之路 0 序

    0 序 近来,由于工作上的需要,开始自学Revit二次开发. Revit由欧特克公司专为BIM构建,是建筑业体系中使用最广泛的软件之一.借助欧特克公司在我国市场占有率方面的绝对优势,甚至给不少人带来& ...