您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

适用于初学者学习的Python正则表达式

时间:2020-07-14 12:15:00  来源:  作者:

“代码胜于雄辩。”

——林纳斯·托瓦兹(Linus Torvalds)

许多编程语言和操作系统都支持正则表达式(regular expression):定义搜索模式的一组字符串。正则表达式可用于检索文件或其他数据中是否存在指定的复杂模式。例如,可使用正则表达式匹配文件中所有的数字。本章将学习如何定义正则表达式,将其传入类UNIX操作系统以用来检索文件的grep命令。该命令会返回文件中与指定模式匹配的文本。我们还将学习在Python中使用正则表达式检索字符串。

17.1 初始配置

开始之前,先创建一个名为zen.txt的文件。在命令行中(确保位于zen.txt所在的目录)输入命令python3 -c "import this",这会打印出蒂姆·皮特斯(Tim Peters)写的诗The Zen of Python(Python之禅):

Python之禅

 

优美胜于丑陋

明了胜于晦涩

简洁胜于复杂

复杂胜于凌乱

扁平胜于嵌套

间隔胜于紧凑

可读性很重要

即便假借特例的实用性之名,也不可违背这些规则

不要包容所有错误,除非你确定需要这样做

当存在多种可能,不要尝试去猜测

而是尽量找一种,最好是唯一一种明显的解决方案

虽然这并不容易,因为你不是Python之父

做也许好过不做,但不假思索就动手还不如不做

如果你无法向人描述你的方案,那肯定不是一个好方案

命名空间是一种绝妙的理念,我们应当多加利用

旗标-c告诉Python传入的字符串中包含有Python代码。然后Python会执行传入的代码。Python执行import this之后,将打印The Zen of Python(像上述这首诗一样隐藏在代码中的信息,也被称为彩蛋)。在Bash中输入exit()函数退出Python,然后将诗的内容复制到文件zen.txt中。

在Ubuntu系统中,grep命令默认在输出时以红色字体打印匹配的文本,但是在UNIX系统中则不是这么做的。如果使用的是mac,可以通过在Bash中修改如下环境变量来改变该行为:

# http://tinyurl.com/z9prphe

$ export GREP_OPTIONS='--color=always'
$ export GREP_OPTIONS='--color=always'

要记住,在Bash中直接设置环境变量的方式是不持久的,如果退出Bash,下次再打开时必须重新设置环境变量。因此,可将环境变量添加至.profile文件,使其持久存在。

17.2 简单匹配

grep命令接受两个参数:一个正则表达式和检索正则表达式中定义模式的文件路径。使用正则表达式进行最简单的模式匹配,就是简单匹配,即一个字符串匹配单词中相同的字符串。举个例子,在zen.txt文件所在的目录输入如下命令:

# http://tinyurl.com/jgh3x4c

$ grep Beautiful zen.txt

>> Beautiful is better than ugly.

上例中执行的命令里,第一个参数Beautiful是一个正则表达式,第二个参数zen.txt是检索正则表达式的文件。Bash打印了Beautiful is better than ugly.这句话,其中Beautiful为红色,因为它是正则表达式匹配上的单词。

如果将上例中的正则表达式从Beautiful修改为beautiful,grep将无法匹配成功:

# http://tinyurl.com/j2z6t2r

$ grep beautiful zen.txt

当然,可以加上旗标-i来忽略大小写:

# http://tinyurl.com/zchmrdq

$ grep -i beautiful zen.txt

>> Beautiful is better than ugly.

grep命令默认打印匹配文本所在的整行内容。可以添加旗标-o,确保只打印与传入的模式参数相匹配的文本:

# http://tinyurl.com/zfcdnmx

$ grep -o Beautiful zen.txt

>> Beautiful

也可通过内置模块re在Python中使用正则表达式。re模块提供了一个叫findall的方法,将正则表达式和目标文本作为参数传入,该方法将以列表形式返回文本中与正则表达式匹配的所有元素:

01  # http://tinyurl.com/z9q2286
02  
03  
04  <strong>import</strong> re
05  
06  
07  l = "Beautiful is better than ugly."
08  
09  
10  matches = re.findall("Beautiful", l)
11  
12  
13  print(matches)

>> ['Beautiful']

本例中findall方法只找到了一处匹配,返回了一个包含匹配结果[Beautiful]的列表。

将re.IGNORECASE作为第3个参数传入findall,可以让其忽略大小写:

01  # http://tinyurl.com/jzeonne
02  
03  
04  <strong>import</strong> re
05  
06  
07  l = "Beautiful is better than ugly."
08  
09  
10  matches = re.findall("beautiful", 
11                        l, 
12                        re.IGNORECASE)
13  
14  
15  print(matches)

>> ['Beautiful']

17.3 匹配起始位置

我们还可以在正则表达式中加入特殊字符来匹配复杂模式,特殊字符并不匹配单个字符,而是定义一条规则。例如,可使用补字符号 ^ 创建一个正则表达式,表示只有模式位于行的起始位置时才匹配成功:

# http://tinyurl.com/gleyzan

$ grep ^If zen.txt

>> If the implementation is hard to explain, it is a bad idea.
>> If the implementation is easy to explain, it may be a good idea.

类似地,还可使用美元符号$来匹配结尾指定模式的文本行:

# http://tinyurl.com/zkvpc2r

$ grep idea.$ zen.txt

>> If the implementation is hard to explain, it is a bad idea.
>> If the implementation is easy to explain, it may be a good idea.

本例中,grep忽略了Namespaces are one honking great idea -- let us do more of those!这行,因为它虽然包含了单词idea,但并不是以其结尾。

下例是在Python中使用补字符 ^ 的示例(必须传入re.MULITILINE作为findall的第3个参数,才能在多行文本中找到所有匹配的内容):

01  # http://tinyurl.com/zntqzc9
02  
03  
04  <strong>import</strong> re
05  
06  
07  zen = """Although never is
08  often better than
09  *right* now.
10  If the implementation
11  is hard to explain,
12  it's a bad idea.
13  If the implementation
14  is easy to explain,
15  it may be a good
16  idea. Namesapces
17  are one honking
18  great idea -- let's
19  do more of those!
20  """
21  
22  
23  m = re.findall("^If",
24                 zen,
25                 re.MULITILINE)
26  print(m)

>> ['If', 'If']

17.4 匹配多个字符

将正则表达式的多个字符放在方括号中,即可定义一个匹配多个字符的模式。如果在正则表达式中加入[abc],则可匹配a、b或c。在下一个示例中,我们不再是直接匹配zen.txt中的文本,而是将字符串以管道形式传给grep进行匹配。示例如下:

# http://tinyurl.com/jf9qzuz

$ echo Two too. <strong>|</strong> grep -i t[ow]o

>> Two too

echo命令的输出被作为输入传给grep,因此不用再为grep指定文件参数。上述命令将two和too都打印出来,是因为正则表达式均匹配成功:第一个字符为t,中间为o或w,最后是o。

Python实现如下:

01  # http://tinyurl.com/hg9sw3u
02  
03  
04  <strong>import</strong> re
05  
06  
07  string = "Two too."
08  
09  
10  m = re.findall("t[ow]o",
11                 string,
12                 re.IGNORECASE)
13  print(m)

>> ['Two', 'too']

17.5 匹配数字

可使用[[:digit:]]匹配字符串中的数字:

# http://tinyurl.com/gm8o6gb

$ echo 123 hi 34 hello. <strong>|</strong> grep [[:digit:]]

>> 123 hi 34 hello.

在Python 中使用d匹配数字:

1  # http://tinyurl.com/z3hr4q8
2  
3  
04  <strong>import</strong> re
05  
06  
07  line = "123?34 hello?"
08  
09  
10  m = re.findall("d",
11                 line,
12                 re.IGNORECASE)
13  
14  
15  print(m)

>> ['1', '2', '3', '3', '4']

17.6 重复

星号符*可让正则表达式支持匹配重复字符。加上星号符之后,星号前面的元素可匹配零或多次。例如,可使用星号匹配后面接任意个o的tw:

# http://tinyurl.com/j8vbwq8

$ echo two twoo not too. <strong>|</strong> grep -o two*

>> two
>> twoo

在正则表达式中,句号可匹配任意字符。如果在句号后加一个星号,这将让正则表达式匹配任意字符零或多次。也可使用句号加星号,来匹配两个字符之间的所有内容:

# http://tinyurl.com/h5x6cal

$ echo __hello__there <strong>|</strong> grep -o __.*__

>> __hello__

正则表达式__.*__可匹配两个下划线之间(包括下划线)的所有内容。星号是贪婪匹配(greedy),意味着会尽可能多地匹配文本。例如,如果在双下划线之间加上更多的单词,上例中的正则表达式也会匹配从第一个下划线到最后一个下划线之间的所有内容:

# http://tinyurl.com/j9v9t24

$ echo __hi__bye__hi__there <strong>|</strong> grep -o __.*__

>> __hi__bye__hi__

如果不想一直贪婪匹配,可以在星号后面加个问号,使得正则表达式变成非贪婪模式(non-greedy)。一个非贪婪的正则表达式会尽可能少地进行匹配。在本例中,将会在碰到第一个双下线后就结束匹配,而不是匹配第一个和最后一个下划线之间的所有内容。grep并不支持非贪婪匹配,但是在Python中可以实现:

01  # http://tinyurl.com/j399sq9
02  
03  
04  <strong>import</strong> re
05  
06  
07  t = "__one__ __two__ __three__"
08  
09  
10  found = re.findall("__.*?__", t)
11  
12  
13  <strong>for</strong> match <strong>in</strong> found:
14      print(match)

>> __one__
>> __two__
>> __three__

我们可通过Python中的非贪婪匹配,来实现游戏Mad Libs(本游戏中会给出一段文本,其中有多个单词丢失,需要玩家来补全):

01  # http://tinyurl.com/ze6oyua
02  
03  <strong>import</strong> re
04  
05  
06  text = """Giraffes have aroused
07   the curIOSity of __PLURAL_NOUN__
08   since earliest times. The
09   giraffe is the tallest of all
10   living __PLURAL_NOUN__, but
11   scientists are unable to
12   explain how it got its long
13   __PART_OF_THE_BODY__. The
14   giraffe's tremendous height,
15   which might reach __NUMBER__
16   __PLURAL_NOUN__, comes from
17   it legs and __BODYPART__.
18  """
19  
20  
21  <strong>def</strong> mad_libs(mls):
22      """
23      :param mls:字符串
24      双下划线部分的内容要由玩家来补充。
25      双下划线不能出现在提示语中,如不能
26      出现 __hint_hint__,只能是 __hint__。
27  
28  
29  
30  
31      """
32      hints = re.findall("__.*?__",
33                         mls)
34      <strong>if</strong> hints <strong>is</strong> <strong>not</strong> None:
35          <strong>for</strong> word <strong>in</strong> hints:
36              q = "Enter a {}".format(word)
37              new = input(q)
38              mls = mls.replace(word, new, 1)
39          <strong>print</strong>("n")
40          mls = mls.replace("n", "")
41          print(mls)
42      <strong>else</strong>:
43          <strong>print</strong>("invalid mls")
44  
45  
46  mad_libs(text)

>> enter a __PLURAL_NOUN__

本例中,我们使用re.findall匹配变量text中所有被双下划线包围的内容(每个均为玩家需要输入答案进行替代的内容),以列表形式返回。然后,对列表中的元素进行循环,通过每个提示来要求玩家提供一个新的单词。之后,创建一个新的字符串,将提示替换为玩家输入的词。循环结束后,打印替换完成后的新字符串。

17.7 转义

我们可以在正则表达式中对字符进行转义(忽略字符的意义,直接进行匹配)。在正则表达式中的字符前加上一个反斜杠即可进行转义:

# http://tinyurl.com/zkbumfj

$ echo I love $ <strong>|</strong> grep \$

>> I love $

通常情况下,美元符号的意思是出现在匹配文本行尾时才有效,但是由于我们进行了转义,这个正则表达式只是匹配目标文本中的美元符号。

Python实现如下:

01  # http://tinyurl.com/zy7pr41
02  
03  
04  <strong>import</strong> re
05  
06  
07  line = "I love $"
08  
09  
10  m = re.findall("\$",
11                 line,
12                 re.IGNORECASE)
13  
14  
15  print(m)

>> ['$']

17.8 正则工具

找到匹配模式的正则表达式是一件很困难的事。可前往http://theselftaughtprogrammer. io/regex了解有助于创建正则表达式的工具。

17.9 术语表

正则表达式:定义检索模式的字符串序列。

菜单:代码中隐藏的信息。

贪婪匹配:尽量多地匹配文本的正则表达式。

非贪婪匹配:尽可能少地进行文本匹配的正则表达式。

本文摘自《Python编程无师自通——专业程序员的养成》



Tags:Python 正则表达式   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
“代码胜于雄辩。”&mdash;&mdash;林纳斯&middot;托瓦兹(Linus Torvalds)许多编程语言和操作系统都支持正则表达式(regular expression):定义搜索模式的一组字符串。正则表达式可...【详细内容】
2020-07-14  Tags: Python 正则表达式  点击:(37)  评论:(0)  加入收藏
为什么要学正则表达式实际上爬虫一共就四个主要步骤:明确目标 (要知道你准备在哪个范围或者网站去搜索) 爬 (将所有的网站的内容全部爬下来) 取 (去掉对我们没用处的数据) 处...【详细内容】
2019-11-22  Tags: Python 正则表达式  点击:(47)  评论:(0)  加入收藏
正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能。正则表...【详细内容】
2019-08-07  Tags: Python 正则表达式  点击:(240)  评论:(0)  加入收藏
▌简易百科推荐
大家好,我是菜鸟哥,今天跟大家一起聊一下Python4的话题! 从2020年的1月1号开始,Python官方正式的停止了对于Python2的维护。Python也正式的进入了Python3的时代。而随着时间的...【详细内容】
2021-12-28  菜鸟学python    Tags:Python4   点击:(1)  评论:(0)  加入收藏
学习Python的初衷是因为它的实践的便捷性,几乎计算机上能完成的各种操作都能在Python上找到解决途径。平时工作需要在线学习。而在线学习的复杂性经常让人抓狂。费时费力且效...【详细内容】
2021-12-28  风度翩翩的Python    Tags:Python   点击:(1)  评论:(0)  加入收藏
Python 是一个很棒的语言。它是世界上发展最快的编程语言之一。它一次又一次地证明了在开发人员职位中和跨行业的数据科学职位中的实用性。整个 Python 及其库的生态系统使...【详细内容】
2021-12-27  IT资料库    Tags:Python 库   点击:(2)  评论:(0)  加入收藏
菜单驱动程序简介菜单驱动程序是通过显示选项列表从用户那里获取输入并允许用户从选项列表中选择输入的程序。菜单驱动程序的一个简单示例是 ATM(自动取款机)。在交易的情况下...【详细内容】
2021-12-27  子冉爱python    Tags:Python   点击:(4)  评论:(0)  加入收藏
有不少同学学完Python后仍然很难将其灵活运用。我整理15个Python入门的小程序。在实践中应用Python会有事半功倍的效果。01 实现二元二次函数实现数学里的二元二次函数:f(x,...【详细内容】
2021-12-22  程序汪小成    Tags:Python入门   点击:(32)  评论:(0)  加入收藏
Verilog是由一个个module组成的,下面是其中一个module在网表中的样子,我只需要提取module名字、实例化关系。module rst_filter ( ...); 端口声明... wire定义......【详细内容】
2021-12-22  编程啊青    Tags:Verilog   点击:(8)  评论:(0)  加入收藏
运行环境 如何从 MP4 视频中提取帧 将帧变成 GIF 创建 MP4 到 GIF GUI ...【详细内容】
2021-12-22  修道猿    Tags:Python   点击:(6)  评论:(0)  加入收藏
面向对象:Object Oriented Programming,简称OOP,即面向对象程序设计。类(Class)和对象(Object)类是用来描述具有相同属性和方法对象的集合。对象是类的具体实例。比如,学生都有...【详细内容】
2021-12-22  我头秃了    Tags:python   点击:(9)  评论:(0)  加入收藏
所谓内置函数,就是Python提供的, 可以直接拿来直接用的函数,比如大家熟悉的print,range、input等,也有不是很熟,但是很重要的,如enumerate、zip、join等,Python内置的这些函数非常...【详细内容】
2021-12-21  程序员小新ds    Tags:python初   点击:(5)  评论:(0)  加入收藏
Hi,大家好。我们在接口自动化测试项目中,有时候需要一些加密。今天给大伙介绍Python实现各种 加密 ,接口加解密再也不愁。目录一、项目加解密需求分析六、Python加密库PyCrypto...【详细内容】
2021-12-21  Python可乐    Tags:Python   点击:(8)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条