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

缩写字符分类 含义
\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. vmware安装linux系统,自动建立没选项

    虚拟机安装CentOS自己跳过分区,直接就到最后的软件包安装了 建完系统后不用power on,建完后在edit一下系统参数,应该会看见两个cd, 有一个是vmware自己加的,把那个删除后在开机就可 ...

  2. Linux数据库的导入导出

    Linux数据库的导入导出 1.导入数据库 mysql -u username -p test < /home/data/test.sql 说明:username是数据库用户名,test为目标数 ...

  3. ElasticSearch 介绍、Docker安装以及基本检索第三篇

    一.简介 1.1 什么是Elasticsearch? Elasticsearch是一个分布式的开源搜索和分析引擎, 适用于所有类型的数据,包括文本.数字.地理空间.结构化和啡结构化数据.Elastic ...

  4. Elasticsearch 之 Filter 与 Query 有啥不同?

    今天来了解下 Elasticsearch(以下简称 ES) 中的 Query 和 Filter. 在 ES 中,提供了 Query 和 Filter 两种搜索: Query Context:会对搜索进 ...

  5. var_dump和var_export区别

    1.var_dump() :获取结构化的数据,按照数组的层级输出 2.var_export() :获取结构化的数据,返回有效的php代码,保留结构化形式的存储数据,数据类型为字符串. 例如: < ...

  6. <<Hive编程指南>>读书笔记

    1. 设置hive以本地模式运行(即使当前用户是在分布式模式或伪分布式模式下执行也使用这种模式) set hive.exec.model.local.auto=true; 若想默认使用这个配置,可以将 ...

  7. 1151 LCA in a Binary Tree

    The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...

  8. HDU6321 Dynamic Graph Matching【状压DP 子集枚举】

    HDU6321 Dynamic Graph Matching 题意: 给出\(N\)个点,一开始没有边,然后有\(M\)次操作,每次操作加一条无向边或者删一条已经存在的边,问每次操作后图中恰好匹配\( ...

  9. ACdream1414 Geometry Problem

    Problem Description       Peter is studying in the third grade of elementary school. His teacher of ...

  10. Codeforces Round #655 (Div. 2) A. Omkar and Completion (构造)

    题意:构造一个长度为\(n\)的序列,要求所有元素总和不大于\(1000\),并且任意两项的和不等于另外一项. 题解:全构造\(1\)就好了. 代码: int t; int n; int main() ...