适用于初学者学习的Python正则表达式(python正则表达式或者用法)

网友投稿 386 2022-09-07


适用于初学者学习的Python正则表达式(python正则表达式或者用法)

目录

​​17.1 初始配置​​

​​17.2 简单匹配​​

​​17.3 匹配起始位置​​

​​17.4 匹配多个字符​​

​​17.5 匹配数字​​

​​17.6 重复​​

​​17.7 转义​​

​​17.8 正则工具​​

​​17.9 术语表​​

“代码胜于雄辩。”——林纳斯·托瓦兹(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中修改如下环境变量来改变该行为:

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

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

17.2 简单匹配

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

# grep Beautiful zen.txt>> Beautiful is better than ugly.

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

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

# grep beautiful zen.txt

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

# grep -i beautiful zen.txt>> Beautiful is better than ugly.

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

# grep -o Beautiful zen.txt>> Beautiful

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

01 # 03 04 import re05 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 # 03 04 import re05 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 匹配起始位置

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

# 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.

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

# 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 # 03 04 import re05 06 07 zen = """Although never is08 often better than09 *right* now.10 If the implementation11 is hard to explain,12 it's a bad idea.13 If the implementation14 is easy to explain,15 it may be a good16 idea. Namesapces17 are one honking18 great idea -- let's19 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​​进行匹配。示例如下:

# echo Two too. | grep -i t[ow]o>> Two too

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

Python实现如下:

01 # 03 04 import re05 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:]]​​匹配字符串中的数字:

# echo 123 hi 34 hello. | grep [[:digit:]]>> 123 hi 34 hello.

在Python 中使用​​\d​​匹配数字:

1 # 3 04 import re05 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​​:

# echo two twoo not too. | grep -o two*>> two>> twoo

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

# echo __hello__there | grep -o __.*__>> __hello__

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

# echo __hi__bye__hi__there | grep -o __.*__>> __hi__bye__hi__

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

01 # 03 04 import re05 06 07 t = "__one__ __two__ __three__"08 09 10 found = re.findall("__.*?__", t)11 12 13 for match in found:14 print(match)>> __one__>> __two__>> __three__

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

01 # 03 import re04 05 06 text = """Giraffes have aroused07 the curiosity of __PLURAL_NOUN__08 since earliest times. The09 giraffe is the tallest of all10 living __PLURAL_NOUN__, but11 scientists are unable to12 explain how it got its long13 __PART_OF_THE_BODY__. The14 giraffe's tremendous height,15 which might reach __NUMBER__16 __PLURAL_NOUN__, comes from17 it legs and __BODYPART__.18 """19 20 21 def 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 if hints is not None:35 for word in hints:36 q = "Enter a {}".format(word)37 new = input(q)38 mls = mls.replace(word, new, 1)39 print("\n")40 mls = mls.replace("\n", "")41 print(mls)42 else:43 print("invalid mls")44 45 46 mad_libs(text)>> enter a __PLURAL_NOUN__

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

17.7 转义

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

# echo I love $ | grep \\$>> I love $

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

Python实现如下:

01 # 03 04 import re05 06 07 line = "I love $"08 09 10 m = re.findall("\\$",11 line,12 re.IGNORECASE)13 14 15 print(m)>> ['$']

17.8 正则工具

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

17.9 术语表

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

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

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

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:在R、Python和Julia中常用的数据可视化技术
下一篇:解决springCache配置中踩的坑
相关文章

 发表评论

暂时没有评论,来抢沙发吧~