龙空技术网

Python 3 高级编程 - 正则表达式

逸剑听潮 372

前言:

此时咱们对“高级python编程”大体比较着重,兄弟们都想要学习一些“高级python编程”的相关文章。那么小编同时在网摘上收集了一些有关“高级python编程””的相关文章,希望大家能喜欢,看官们一起来学习一下吧!

正则表达式在pthon编程中经常用到,如果写过爬虫程序的伙伴一定对正则不会陌生的。

正则表达式是一种特殊的字符序列,可帮助您使用模式中包含的专用语法匹配或查找其他字符串或字符串集。正则表达式在 UNIX 世界中被广泛使用。

Python 中 re 模块提供了正则表达式的实现。如果在编译或使用正则表达式时发生错误,则 re 模块会引发异常 re.error。

正则表达式用到的匹配符号的含义:

a, X, 9, < 等单个字符,普通字符只是完全匹配自己. (点), 匹配除换行符 '\n' 之外的任何单个字符\w,匹配“单词”字符:字母或数字或下划线 [a-zA-Z0-9_]\W,匹配任何非单词字符\b,词与非词的边界\s,匹配单个空白字符——空格、换行符、回车符、制表符\S,匹配任何非空白字符\t, \n, \r,制表符、换行符、回车\d,匹配十进制数字 [0-9]^,匹配字符串的开头$,匹配字符串的结尾\,转义特殊字符

编译标志

编译标志允许修改正则表达式工作方式的某些方面。 re 模块中的标志有两个名称,一个是长名称,如 IGNORECASE,另一个是短的单字母形式,如 I。

ASCII, A 使多个转义符如 \w、\b、\s 和 \d 仅匹配具有相应属性的 ASCII 字符。DOTALL, S 制作,匹配任何字符,包括换行符IGNORECASE, I 进行不区分大小写的匹配LOCALE, L 进行语言环境感知匹配MULTILINE, M 多行匹配,影响^和$VERBOSE, X (for ‘extended’) 启用冗长的 RE,可以将其组织得更清晰、更易于理解匹配函数

match 函数尝试将 RE 模式与带有可选标志的字符串匹配。匹配函数的语法:

re.match(pattern, string, flags = 0)

参数的含义:

pattern 要匹配的正则表达式string 字符串,将搜索它以匹配字符串开头的模式flags 是修饰符,使用按位或 (|) 指定不同的标志。

re.match 函数在成功时返回一个匹配对象,在失败时返回 None。使用匹配对象的 group(num) 或 groups() 函数来获取匹配的表达式。

group(num = 0) 此方法返回整个匹配项(或特定子组编号)groups() 此方法返回元组中所有匹配的子组(如果没有则为空)

例如:

import reline = "I want to watch a movie"matchObj = re.match( r'(.*) to (.*?) .*', line, re.M|re.I)if matchObj:   print ("matchObj.group() : ", matchObj.group())   print ("matchObj.group(1) : ", matchObj.group(1))   print ("matchObj.group(2) : ", matchObj.group(2))else:   print ("No match!!")

运行结果:

matchObj.group() :  I want to watch a moviematchObj.group(1) :  I wantmatchObj.group(2) :  watch
搜索功能

search 函数使用可选标志在字符串中搜索 RE 模式的第一次出现。语法:

re.search(pattern, string, flags = 0)

参数含义:

pattern 要匹配的正则表达式string 字符串,将搜索它以匹配字符串开头的模式flags 是修饰符,使用按位或 (|) 指定不同的标志。

re.search 函数在成功时返回一个匹配对象,在失败时返回一个匹配对象。使用匹配对象的 group(num) 或 groups() 函数来获取匹配的表达式。

group(num = 0) 此方法返回整个匹配项(或特定子组编号)groups() 此方法返回元组中所有匹配的子组(如果没有则为空)

例如:

import reline = "I want to watch a movie"searchObj  = re.search( r'(.*) to (.*?) .*', line, re.M|re.I)if matchObj:   print ("searchObj .group() : ", searchObj .group())   print ("searchObj .group(1) : ", searchObj .group(1))   print ("searchObj .group(2) : ", searchObj .group(2))else:   print ("No match!!")

运行结果:

searchObj .group() :  I want to watch a moviesearchObj .group(1) :  I wantsearchObj .group(2) :  watch
匹配 match与搜索 search

Python 提供了两种基于正则表达式的不同原始操作:匹配仅检查字符串开头的匹配项,而搜索检查字符串中任何位置的匹配项。例如:

import reline = "I want to watch a movie";matchObj = re.match( r'movie', line, re.M|re.I)if matchObj:   print ("match --> matchObj.group() : ", matchObj.group())else:   print ("No match!!")searchObj = re.search( r'movie', line, re.M|re.I)if searchObj:   print ("search --> searchObj.group() : ", searchObj.group())else:   print ("Nothing found!!")

运行结果:

No match!!search --> searchObj.group() :  movie
搜索和替换

使用正则表达式的最重要的 re 方法之一 sub 实现搜索替换。语法:

re.sub(pattern, repl, string, max=0)

此方法用 repl 替换字符串中所有匹配给定 RE 正则表达式的地方,替换所有匹配项,除非达到了 max 的限制数量。此方法返回修改后的字符串。

import recode = "100-1001-210 # This is a code"num = re.sub(r'#.*$', "", phone)   # 去除注释部分print ("Code Num : ", num)num = re.sub(r'\D', "", phone)     #去除除了数字之外的所有字符print ("Code Num : ", num)num = re.sub(r'\D', " ", phone)      #数字之外的所有字符用空格代替print ("Code Num : ", num)

运行结果:

Code Num :  100-1001-210 Code Num :  1001001210Code Num :  100 1001 210    

正则表达式修饰符:可选标志

则表达式文字可能包括一个可选的修饰符来控制匹配的各个方面。修饰符被指定为可选标志。可以使用异或 (|) 使用多个修饰符,如前面例子中的re.M|re.I。这些修饰符的含义如下:

re.I 执行不区分大小写的匹配。re.L 根据当前语言环境解释单词。这种解释会影响字母组(\w 和 \W)以及单词边界行为(\b 和 \B)。re.M 使 $ 匹配行的结尾(不仅仅是字符串的结尾)并使 ^ 匹配任何行的开头(而不仅仅是字符串的开头)。re.S 使.(点)匹配任何字符,包括换行符。re.U 根据 Unicode 字符集解释字母。此标志影响 \w、\W、\b、\B 的行为。re.X 忽略空格(集合 [] 内或被反斜杠转义时除外)并将未转义的 # 视为注释标记。正则表达式模式

除控制字符 (+ ? . * ^ $ ( ) [ ] { } | \) 外,所有字符都只能匹配自己。可以通过在控制字符前加上反斜杠来转义控制字符。

字符匹配,示例及说明:

python 匹配整个“python”字符串[Pp]ython 匹配“Python”或“python”rub[ye] 匹配“ruby”或“rube”[aeiou] 匹配任何一个小写元音字母[0-9] 匹配任意数字;与 [0123456789] 相同[a-z] 匹配任何小写 ASCII 字母[A-Z] 匹配任何大写 ASCII 字母[a-z -Z0-9] 匹配任何大写小写字母和数字[^aeiou] 匹配小写元音以外的任何内容[^0-9] 匹配数字以外的任何内容

例如:

import re r = r"Python"str = "It's easy to learn python. Python is simple."m = re.search(r, str)print(m) r1 = r"[Pp]ython"   #匹配 python或 Pythonm1 = re.search(r1, str)print(m1)r2 = r"[a-z]"    #匹配一个小写字母m2 = re.search(r2, str)print(m2)

运行结果

<re.Match object; span=(27, 33), match='Python'><re.Match object; span=(19, 25), match='python'><re.Match object; span=(1, 2), match='t'>

特殊字符匹配

. (点) 匹配除换行符以外的任何字符\d 匹配数字:[0-9]\D 匹配一个非数字:[^0-9]\s 匹配空白字符:[ \t\r\n\f]\S 匹配非空白:[^ \t\r\n\f]\w 匹配单个单词字符:[A-Za-z0-9_]\W 匹配一个非单词字符:[^A-Za-z0-9_]

例如:

import re r = r"\d"   #匹配一个数字str = "Python 3.0 was released in 2008."m = re.search(r, str)print(m)r1 = r"\w"   #匹配一个大写,小写或数字m1 = re.search(r1, str)print(m1)

运行结果:

<re.Match object; span=(7, 8), match='3'><re.Match object; span=(0, 1), match='P'>

重复匹配

? 重复前面一个匹配字符零次或者一次。例如 ruby? 匹配“rub”或“ruby”* 重复前面一个匹配字符零次或者多次。例如 ruby* 匹配“rub”或“rubyyy”可加多个y+ 重复前面一个匹配字符一次或者多次。例如 ruby* 匹配“ruby”或“rubyyy”可加多个y{n} 匹配 n 个字符。例如 ruby{3} 匹配 “ruby”后可加任意3个字符,“rubyabc”{m,n} 匹配 m 到 n 个字符。例如 ruby* 匹配{n,} 匹配 n 个或多个字符。例如 ruby* 匹配

例如:

import re r = r"Py?"   #匹配前面字符零次或者一次m = re.search(r, "Python")  #匹配前面字符一次print(m)m = re.search(r, "P0ython")  #匹配前面字符零次print(m)r=r"Py+"  #匹配字符一次或者多次m=re.search(r,"Python")  #匹配字符一次print(m)m=re.search(r,"Pyyython")  #匹配字符零次或者多次print(m) r=r"Py*"   #匹配字符零次或者多次m=re.search(r,"P0ython")  #匹配字符一次print(m)m=re.search(r,"Pyyython")  #匹配字符零次或者多次print(m)r=r"Py{4}"   #匹配前面字符4次m=re.search(r,"Pyyyyyyython")  #匹配字符4次print(m)r=r"Py{4,}"   #匹配前面字符4次或更多次m=re.search(r,"Pyyyyyyyyyyyyyyyython")  #匹配字符多次print(m)

运行结果

<re.Match object; span=(0, 2), match='Py'><re.Match object; span=(0, 1), match='P'><re.Match object; span=(0, 2), match='Py'><re.Match object; span=(0, 4), match='Pyyy'><re.Match object; span=(0, 1), match='P'><re.Match object; span=(0, 4), match='Pyyy'><re.Match object; span=(0, 5), match='Pyyyy'><re.Match object; span=(0, 17), match='Pyyyyyyyyyyyyyyyy'>

非贪婪重复匹配

匹配最少的重复次数。

防止过度匹配

贪婪匹配:

+ 是贪婪匹配,匹配次数只接受一次或者多次,例如 pythonn+ 中的红色 n 如果出现在 python 后面出现一次 n 的时候,立刻返回匹配成功的值,同时由于是贪婪匹配,在 python 后面出现两或多个 n 的时候,也会返回匹配成功的值。当 n 为零次的时候,即为 python 时,是不会有返回值的!

import rer=r"pythonn+"   #贪婪匹配m=re.search(r,"pythonnnnn")   print(m)#运行结果<re.Match object; span=(0, 10), match='pythonnnnn'>

*贪婪匹配,匹配次数接受零次一次或者多次,此时 pythonn+ 中的红色 n 如果出现在 python 后面出现零次的时候,立刻返回匹配成功的值,同时由于是贪心匹配,在 python 后面出现一个或多个 n时,也会返回匹配成功的值。

import rer=r"pythonn*"   #贪婪匹配m=re.search(r,"pythonnnnn")   print(m)#运行结果<re.Match object; span=(0, 10), match='pythonnnnn'>

?是非贪婪匹配,匹配次数只接受零次或者一次,同时如果零次满足,则一次匹配不再继续。例如 pythonn+ 中的红色 n 如果出现在 python 后面出现零次的时候,立刻返回匹配成功的值,同时由于是非贪心匹配,在 python 后面出现一个或多个 n 的时候,也不会匹配。

import rer=r"pythonn?"   #非贪婪匹配m=re.search(r,"python")   print(m)m=re.search(r,"pythonnnnn")   print(m)#运行结果<re.Match object; span=(0, 6), match='python'><re.Match object; span=(0, 7), match='pythonn'>

控制贪婪匹配

在 * 和 + 后面加上 ?就是把贪婪匹配更改为非贪婪匹配:

* 号后面加 ?变成非贪婪匹配,匹配 0 次成功就会退出匹配。

+ 号后面加上 ?变成非贪婪匹配,匹配1次成功就会推出匹配。

例如:

import rer=r"pythonn+?"   #非贪婪匹配,1次匹配m=re.search(r,"pythonnnnnnnnn")   print(m)r=r"pythonn*?"   #非贪婪匹配,0次匹配m=re.search(r,"pythonnnn")   print(m)#运行结果<re.Match object; span=(0, 7), match='pythonn'><re.Match object; span=(0, 6), match='python'>

搞懂了贪婪匹配,非贪婪匹配,什一次匹配,多次匹配之后,就可以灵活运用正则匹配了。

用括号分组

\D\d+ 无分组:+ 重复 \d

(\D\d)+ 分组:+ 重复 \D\d 对

例如:([Pp]ython(,)?)+ 匹配“Python”、“Python, python, pythonnnnnn”等。

import rer = r"([Pp]ython(,)?)+"   #分组匹配m = re.search(r,"Python")   print(m)r = r"([Pp]ython(,)?)+"   #分组匹配m = re.search(r,"pythonnnnnnnn Python  python")   print(m)#运行结果<re.Match object; span=(0, 6), match='Python'><re.Match object; span=(0, 6), match='python'>
反向引用(\)

再次匹配先前匹配的分组。例如

([Pp])ython&\1ails 匹配 python&pails 或 Python&Pails

(['"])[^\1]*\1 单引号或双引号字符串。 \1 匹配第一组匹配的任何内容。 \2 匹配第二组匹配的任何内容,等等。

备择方案(|)

python|perl 匹配“python”或“perl”

rub(y|le) 匹配"ruby" 或"ruble"

Python(!+|\?) “Python”后跟一个或多个!还是一个?

锚点

指定匹配位置.

^ 匹配字符串的开头。

$ 匹配字符串的末尾。

\A 匹配字符串开始

\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。

\z 匹配字符串结束

\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。Python(?=!) 如果后跟感叹号,则匹配“Python”

(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。Python(?!!) 如果后面没有感叹号,则匹配“Python”。

带括号的特殊语法

R(?#comment) 匹配“R”。剩下的都是注释

R(?i)uby 匹配“uby”时不区分大小写

R(?i:uby) 匹配“uby”时不区分大小写

rub(?:y|le)) 仅分组而不创建 \1 反向引用

复杂例子,判断电话号码和邮箱地址:

import re americaPhoneRegex = re.compile(r'''(    (\d{3}|\(\d{3}\))?   # area code    (\s|-|\.)?           # separator    (\d{8})              # first 8 digits    (\s|-|\.)            # separator    (\d{4})              # last 4 digits    (\s*(ext|x|ext.)\s*(\d{2,5}))?   # extension    )''', re.VERBOSE)     emailPhoneRegex   = re.compile(r'''(        [a-zA-Z0-9._%+-]+      # username        @                      # @ symbol        [a-zA-Z0-9.-]+         # domain name        (\.[a-zA-Z]{2,4})      # dot-something        )''', re.VERBOSE)  phone = '029-12341234-1234'email = "123@mail.com"matches = []for groups in americaPhoneRegex.findall(phone):    phoneNum = '-'.join([groups[1], groups[3], groups[5]])    if groups[8] != '':        phoneNum += ' x' + groups[8]    matches.append(phoneNum) for groups in emailPhoneRegex.findall(email):    matches.append(groups[0]) if len(matches) > 0:    print('\n'.join(matches))else:    print('No phone numbers or email addresses found.')

标签: #高级python编程