正则表达式命令详解

一、正则表达式简介

正则表达式(regex)
由一些字符和特殊符号组成的字符串,描述了模式的重复或者表述多个字符,可以按照某种模式匹配一系列有相似特征的字符串。为高级的文本模式匹配、抽取、与/或文本形式的搜索和替换功能提供了基础。

也就是是说,使用正则表达式能够匹配多个既定规则的字符串。在严格表述与字符串中模式相关的正则表达式时,一般使用术语“匹配”(matching),即专业术语“模式匹配”(pattern-matching)。

Python中的正则
Python 通过标准库中的 re 模块来支持正则表达式。

Python 术语中,主要有两种方法完成模式匹配:

  • 搜索(searching):在字符串任意部分中搜索匹配的模式;通过 search()函数或方法来实现
  • 匹配(matching):指判断一个字符串能否从起始处全部或者部分地匹配某个模式;通过调用 match()函数或方法实现。

二、正则表达式

正则表达式的强大之处在于引入特殊字符来定义字符集、匹配子组和重复模式。正是由于这些特殊符号,给予了正则表达式强大的
功能和灵活性使,得正则表达式可以匹配字符串集合,而不仅仅只是某单个字符串。

2.1、正则表达式中的特殊符号:

特殊符号描述正则表达式示例
literal匹配文本字符串的字面值 literalaaa
.匹配任何字符(除了\n 之外)aaa
re1|re2匹配正则表达式 re1 或者 re2$2
^匹配字符串起始部分^aa
$匹配字符串终止部分bin/*sh$
*匹配 0 次或者多次前面出现的正则表达式[A-Za-z0-9]*
+匹配 1 次或者多次前面出现的正则表达式[a-z]+.com
?匹配 0 次或者 1 次前面出现的正则表达式go?
{N}匹配 N 次前面出现的正则表达式[0-9]{3}
{M,N}匹配 M~N 次前面出现的正则表达式[0-9]{5,9}
[…]匹配来自字符集的任意单一字符[aeiou]
[x-y]匹配 x~y 范围中的任意单一字符[0-9], [A-Za-z]
[^…]不匹配此字符集中出现的任何一个字符,包括某一范围的字符(如果在此字符集中出现)[^A-Za-z0-9] ,[^aeiou]
(*|+|?|{})?用于匹配上面频繁出现/重复出现符号的非贪婪版本(*、+、?、{}).*?[a-z]
(…)匹配封闭的正则表达式,然后另存为子组([0-9]{3})?,f(oo

择一匹配符号
即管道符号(|),也就是键盘上的竖线,表示一个“从多个模式中选择其一”的操作,用于分割不同的正则表达式。

正则表达式匹配的字符串
aa|bbaa或bb
aa|bb|ccaa或bb或cc

匹配任意单个字符
即英文格式句点(.)符号,匹配除了换行符\n 以外的任何一个字符,无论字母、数字、空格(并不包括“\n”换行符)、可打印字符、不可打印字符。
Python中编译标记[S 或者 DOTALL],该标记能够推翻该限制,从而能够匹配换行符。

正则表达式匹配的字符串
a.z匹配在字母“a”和“z”之间的任意一个字符;例如 abz、a6z、a#z 等
..任意两个字符
.end匹配在字符串 end 之前的任意一个字符
\.匹配英文格式句点

字符串起始、结尾、边界
字符串的起始匹配符:
即脱字符(^)或者特殊字符\A(反斜线和大写字母 A)

字符串的结尾匹配符:
即美元符号($)或者\Z

正则表达式匹配的字符串
^from任何以 From 作为起始的字符串
enn$任何以enn作为结尾的字符串
^ff:ee$任何由单独的字符串 ff:ee 构成的字符串
\$$任何以美元符号($)结尾的字符串
THE任何包含 THE 的字符串
\bTHE任何以 THE 开始的字符串
\bTHE\b仅仅匹配单词 THE
\BTHE任何包含但并不以 THE 作为起始的字符串

字符集匹配符
即方括号[],可以匹配特定字符,还支持匹配指定的字符范围。
方括号中两个符号中间用连字符(-)连接,用于指定一个字符的范围,例如,A-Z、a-z 或者 0-9 分别用于表示大写字母、小写字母和数值数字。

正则表达式匹配的字符串
a[admin]zaaz、adz、amz、aiz、anz中任意一个
[ab][34][cd][56]一个包含四个字符的字符串,第一个字符是“a”或“b”,然后是“3”或“4”,后面是“c”或“d”,最后要么是“5”要么是“6”。例如,a3c5、b4d6 等
z.[0-9]字母“z”后面跟着任何一个字符,然后跟着一个数字
[a-d][efgh-i][A-Z]第一个为a、b、c、d中的任意一个,第二个为e、f、g、h、i中的任意一个,第三个为A到Z之间的任意一个

否定字符
如果脱字符(^)紧跟在左方括号后面,这个符号就表示不匹配给定字符集中的任何一个字符。

正则表达式匹配的字符串
[^aeiou]一个非元音字符
[^\t\n]不匹配制表符或者\n
[“-a]在一个 ASCII 系统中,所有字符都位于“”和“a”之间,即 34~97 之间

闭包操作符
最常用的正则表达式符号一般为星号操作符()、加号操作符(+)、重载操作符(?)。
星号操作符(
),匹配其左侧出现0次或多次,在计算机编程语言和编译原理中,该操作称为 Kleene 闭包。
加号(+)操作符,匹配一次或者多次(也叫做正闭包操作符)。

正则表达式匹配的字符串
[dn]ot?字母“d”或者“n”,后面跟着一个“o”,然后是最多一个“t”,例如,do、no、dot、not
0?[1-9]任何数值数字,它可能前置一个“0”,例如,匹配一系列数(表示从 1~9 的数值),不管是一个还是两个数字
[0-9]{15,16}匹配 15 或者 16 个数字(例如信用卡号码)
</?[^>]+>匹配全部有效的(和无效的)HTML 标签
[KQRBNP][a-h][1-8]-[a-h][1-8]在“长代数”标记法中,表示国际象棋合法的棋盘移动(仅移动,不包括吃子和将军)。即“K”、“Q”、“R”、“B”、“N”或“P”等字母后面加上“a1”~“h8”之间的棋盘坐标。前面的坐标表示从哪里开始走棋,后面的坐标代表走到哪个位置(棋格)上

2.2、正则表达式中的特殊字符:

特殊字符描述正则表达式示例
\d匹配任何十进制数字,与[0-9]一致(\D 与\d 相反,不匹配任何非数值型的数字)data\d+.txt
\w匹配任何字母数字字符,与[A-Za-z0-9_]相同(\W 与之相反)[A-Za-z_]\w+
\s匹配任何空格字符,与[\n\t\r\v\f]相同(\S 与之相反)of\sthe
\b匹配任何单词边界(\B 与之相反)\bThe\b
\N匹配已保存的子组 N(参见上面的(…))price: \16
\c逐字匹配任何特殊字符 c(即,仅按照字面意义匹配,不匹配特殊含义)., \, * ., \, *
\A(\Z)匹配字符串的起始(结束)(另见上面介绍的^和$)\ADear
\f匹配一个换页符,等价于 \x0c 和 \cL
\n匹配一个换行符,等价于 \x0a 和 \cJ
\r匹配一个回车符,等价于 \x0d 和 \cM
\t匹配一个制表符,等价于 \x09 和 \cI
\v匹配一个垂直制表符,等价于 \x0b 和 \cK

特殊字符表示字符集
特殊字符\d 表示匹配任何十进制数字,\w表示全部字母数字的字符集(相当于[A-Za-z0-9_]),\s 可以用来表示空格字符,这些特殊字符的
大写版本表示不匹配。特殊字符组合使用,可以表示更复杂的示例。

正则表达式匹配的字符串
\w±\d+一个由字母数字组成的字符串和一串由一个连字符分隔的数字
[A-Za-z]\w*第一个字符是字母;其余字符(如果存在)可以是字母或者数字(几乎等价于 Python 中的有效标识符)
\d{3}-\d{3}-\d{4}美国电话号码的格式,前面是区号前缀,例如 800-555-1212
\w+@\w+.com以 XXX@YYY.com 格式表示的简单电子邮件地址

2.3、正则表达式中的扩展表示法:

扩展表示法描述正则表达式示例
(?iLmsux)在正则表达式中嵌入一个或者多个特殊“标记”参数(或者通过函数/方法)(?x),(? im)
(?..)表示一个匹配不用保存的分组(?:\w+.)*
(?P…)像一个仅由 name 标识而不是数字 ID 标识的正则分组匹配(?P)
(?P=name)在同一字符串中匹配由(?P<name)分组的之前文本(?P=data)
(?#…)表示注释,所有内容都被忽略(?#comment)
(?=…)匹配条件是如果…出现在之后的位置,而不使用输入字符串;称作正向前视断言(?=.com)
(?!…)匹配条件是如果…不出现在之后的位置,而不使用输入字符串;称作负向前视断言(?!.net)
(?<=…)匹配条件是如果…出现在之前的位置,而不使用输入字符串;称作正向后视断言(?<=800-)
(?<!…)匹配条件是如果…不出现在之前的位置,而不使用输入字符串;称作负向后视断言(?<!192.168.)
(?(id/name)Y|N )如果分组所提供的 id 或者 name(名称)存在,就返回正则表达式的条件匹配 Y,如果不存在,就返回 N;|N 是可选项(?(1)y|x)

圆括号指定分组
对于之前匹配成功的数据,在确定整个字符串是否匹配标准后,若想提取任何已经成功匹配的特定字符串或者子字符串,则需要引入圆括号来进行分组,这样匹配模式的子字符串可以保存起来供后续使用,这些子组能够被同一次的匹配或者搜索重复调用,或者提取出来用于后续处理。

使用正则表达式时,一对圆括号可以实现以下任意一个(或者两个)功能:

  • 对正则表达式进行分组;
  • 匹配子组。

应用场景:

  • 两个不同的正则表达式,想用它们来比较同一个字符串;
  • 对正则表达式进行分组可以在整个正则表达式中使用重复操作符。
正则表达式匹配的字符串
\d+(.\d*)?表示简单浮点数的字符串;也就是说,任何十进制数字,后面可以接一个小数点和零个或者多个十进制数字,例如“0.004”、“2”、“75.”等
(Mr?s?.)?[A-Z][a-z]*[A-Za-z-]+名字和姓氏,以及对名字的限制(如果有,首字母必须大写,后续字母小写),全名前可以有可选的“Mr.”、“Mrs.”、“Ms.”或者“M.”作为称谓,以及灵活可选的姓氏,可以有多个单词、横线以及大写字母

扩展表示法
以问号开始(?…),通常用于在判断匹配之前提供标记,实现一个前视(或者后视)匹配,或者条件检查。尽管圆括号使用这些符号,但是只有(?P)表述一个分组匹配,所有其他的都没有创建一个分组。

正则表达式匹配的字符串
(?:\w+.)*以句点作为结尾的字符串,例如“google.”、“twitter.”、“facebook.”,但是这些匹配不会保存下来供后续的使用和数据检索
(?#comment)此处并不做匹配,只是作为注释
(?=.com)如果一个字符串后面跟着“.com”才做匹配操作
(?!.net)如果一个字符串后面不是跟着“.net”才做匹配操作
(?<=800-)如果字符串之前为“800-”才做匹配,比如:电话号码
(?<!192.168.)如果一个字符串之前不是“192.168.”才做匹配操作,比如:过滤掉一组 C 类 IP 地址
(?(1)y|x)如果一个匹配组 1(\1)存在,就与 y 匹配;否则,就与 x 匹配

三、Python中的正则表达式之re 模块

Python 中通过使用 re 模块来支持正则表达式。

3.1、核心函数match、search

match(pattern,string,flags=0)
匹配字符串,带有可选标记的正则表达式的模式。匹配成功,返回匹配对象;匹配失败,返回 None。
只要模式从字符串的起始部分开始匹配,即使字符串比模式长,匹配也仍然能够成功

import re

r1 = re.match('test', 'test')

if r1 is not None:
    g = r1.group()
    print(g)
# 输出结果:test

r2 = re.match('test', 'test , The Second test demo')
if r2 is not None:
    g = r2.group()
    print(g)
# 输出结果:test

r3 = re.match('test', 'The test demo').group()
print(r3)
# 输出结果:AttributeError: 'NoneType' object has no attribute 'group'

search(pattern,string,flags=0)
搜索,带有可选标记的搜索字符串中第一次出现的正则表达式模式。匹配成功,返回匹配对象;匹配失败,返回 None。
在任意位置对给定正则表达式模式搜索第一次出现的匹配情况,概率远大于出现在字符串起始部分的概率。

import re

r1 = re.search('test', 'test')
if r1 is not None:
    g = r1.group()
    print(g)
# 输出结果:test

r2 = re.search('test', 'test , The Second test demo')
if r2 is not None:
    g = r2.group()
    print(g)
# 输出结果:test

r3 = re.search('test', 'The test demo').group()
print(r3)
# 输出结果:test

3.2、group()、 groups()

group(num=0):
匹配对象的 group()方法能够用于显示那个成功的匹配。返回整个匹配对象,或者编号为 num 的特定子组。
如果匹配失败,将会抛出 AttributeError 异常(None 是返回的错误值,该值并没有 group()属性[方法]),解决该异常添加if语句即可。

groups(default=None):
返回一个包含所有匹配子组的元组(如果没有成功匹配,则返回一个空元组)。

groupdict(default=None)
返回一个包含所有匹配的命名子组的字典,所有的子组名称作为字典的键(如果没有
成功匹配,则返回一个空字典)

3.3、查找每一次出现的位置findall()、finditer()

findall(pattern,string [, flags] )
查找字符串中所有(非重复)出现的正则表达式模式,返回一个匹配列表。

r1 = re.findall('car', 'car')
print(r1)
# 输出结果:['car']

r2 = re.findall('car', 'scary')
print(r2)
# 输出结果:['car']

r3 = re.findall('car', 'carry the barcardi to the car')
print(r3)
# 输出结果:['car', 'car', 'car']

finditer(pattern,string [, flags] )
与 findall()函数相同,但返回的不是一个列表,而是一个迭代器。对于每一次匹配,迭代器都返回一个匹配对象。

import re

s = 'This and that.'
r1 = re.findall(r'(th\w+) and (th\w+)', s, re.I)
print(r1)
# 输出结果:[('This', 'that')]

r2 = re.finditer(r'(th\w+) and (th\w+)', s, re.I)
print(type(r2))
# 输出结果:<class 'callable_iterator'>
for i in r2:
    print(i.groups()) # 输出结果:('This', 'that')
    print(i.group())  # 输出结果:This and that
    print(i.group(1)) # 输出结果:This
    print(i.group(2)) # 输出结果:that


r5 = [g.groups() for g in re.finditer(r'(th\w+) and (th\w+)', s, re.I)]
# 输出结果:print(r5)
[('This', 'that')]

3.4、compile()函数编译正则表达式

在模式匹配发生之前,正则表达式模式必须编译成正则表达式对象。由于正则表达式在执行过程中将进行多次比较操作,因此强烈建议使
用预编译。既然正则表达式的编译是必需的,那么使用预编译来提升执行性能无疑是明智之举。re.compile()能够提供此功能。

模块函数会对已编译的对象进行缓存,所以不是所有使用相同正则表达式模式的 search()和 match()都需要编译。

purge():清除隐式编译的正则表达式模式

**compile(pattern,flags = 0) **:
使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象。
推荐预编译,但并不是必需的。如果需要编译,就使用编译过的方法;如果不需要编译,就使用函数。方法和函数名字相同

常用的模块属性(用于大多数正则表达式函数的标记):

属性描述
re.I、re.IGNORECASE不区分大小写的匹配
re.L、re.LOCALE根据所使用的本地语言环境通过\w、\W、\b、\B、\s、\S 实现匹配
re.M、re.MULTILINE^和$分别匹配目标字符串中行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾
re.S、rer.DOTALL“.”(点号)通常匹配除了\n(换行符)之外的所有单个字符;该标记表示“.”(点号)能够匹配全部字符
re.X、re.VERBOSE通过反斜线转义,否则所有空格加上#(以及在该行中所有后续文字)都被忽略,除非在一个字符类中或者允许注释并且提高可读性

3.5、搜索与替换sub()、subn()

sub(pattern,repl,string,count=0)
sub()和 subn()这两个函数/方法用于实现搜索和替换功能,几乎一样,subn()还返回一个表示替换的总数。
使用 repl 替换所有正则表达式的模式在字符串中出现的位置,除非定义 count,否则就将替换所有出现的位置(另见 subn()函数,该函数返回替换操作的数目)。

import re

r1 = re.sub('X', 'Mr. Smith', 'attn: X\n\nDear X,\n')
print(r1)
'''输出结果:
attn: Mr. Smith

Dear Mr. Smith,
'''

r2 = re.subn('X', 'Mr. Smith', 'attn: X\n\nDear X,\n')
print(r2)
# 输出结果:('attn: Mr. Smith\n\nDear Mr. Smith,\n', 2)

r3 = re.sub('[ae]', 'X', 'abcdef')
print(r3)
# 输出结果:XbcdXf

r4 = re.subn('[ae]', 'X', 'abcdef')
print(r4)
# 输出结果:('XbcdXf', 2)

3.6、限定模式上使用 split()分隔字符串

split(pattern,string,max=0)
根据正则表达式的模式分隔符,split 函数将字符串分割为列表,然后返回成功匹配的列表,分隔最多操作 max 次(默认分割所有匹配成功的位置)。

import re

r1 = re.split(':', 'str1:str2:str3')
print(r1)
# 输出结果:['str1', 'str2', 'str3']

DATA = ('Mountain View,CA 94040','Sunnyvale,CA','Los Altos, 94023','Cupertino 95014', 'Palo Alto CA')
for data in DATA:
    print(re.split(',|(?= (?:\d{5}|[A-Z]{2})) ',data)) # 空格紧跟在五个数字(ZIP 编码)或者两个大写字母(美国联邦州缩写)之后,就用 split 语句分割该空格
''' 输出结果:
['Mountain View', 'CA', '94040']
['Sunnyvale', 'CA']
['Los Altos', '', '94023']
['Cupertino', '95014']
['Palo Alto', 'CA']
'''

3.7、 择一匹配(|)符号

择一匹配(|)符号:
用来匹配多个字符串。

bt = 'bat|bet|bit'      # 正则表达式模式: bat、bet、bit
m = re.match(bt, 'bat') # 'bat' 是一个匹配
if m is not None:
    print(m.group())
# 输出结果:bat

m = re.match(bt, 'blt') # 对于 'blt' 没有匹配
if m is not None:
    print(m.group())
# 无输出结果

m = re.match(bt, 'He bit me!') # 不能匹配字符串
if m is not None:
    print(m.group())
# 无输出结果

m = re.search(bt, 'He bit me!') # 通过搜索查找 'bit'
if m is not None:
    print(m.group())
# 输出结果:bit

3.8、点号(.)

点号(.):
匹配任何单个字符,但不能匹配一个换行符\n 或者非字符(空字符串)。

anyend = '.end'
m = re.match(anyend, 'bend') # 点号匹配 'b'
if m is not None:
    print(m.group())
# 输出结果:'bend'

m = re.match(anyend, 'end') # 不匹配任何字符
if m is not None:
    print(m.group())
# 无输出结果:

m = re.match(anyend, '\nend') # 除了 \n 之外的任何字符
if m is not None:
    print(m.group())
# 无输出结果:

m = re.search('.end', 'The end.')# 在搜索中匹配 ' '
if m is not None:
    print(m.group())
# 输出结果:'end'

3.9、创建字符集([ ])

m = re.match('[cr][23][dp][o2]', 'c3po')# 匹配 'c3po'
if m is not None:
    print(m.group())
# 输出结果:'c3po'

m = re.match('[cr][23][dp][o2]', 'c2do')# 匹配 'c2do'
if m is not None:
    print(m.group())
# 输出结果:'c2do'

m = re.match('r2d2|c3po', 'c2do')# 不匹配 'c2do'
if m is not None:
    print(m.group())
# 无输出结果

m = re.match('r2d2|c3po', 'r2d2')# 匹配 'r2d2'
if m is not None:
    print(m.group())
# 输出结果:'r2d2'

3.10、重复、特殊字符以及分组

允许.com 前面有一个或者两个名称:

patt = '\w+@(\w+\.)?\w+\.com'
g1 = re.match(patt, 'nobody@xxx.com').group()
print(g1)
# 输出结果:'nobody@xxx.com'

g2 = re.match(patt, 'nobody@www.xxx.com').group()
print(g2)
# 输出结果:'nobody@www.xxx.com'

patt = '\w+@(\w+\.)*\w+\.com'
g3 = re.match(patt, 'nobody@www.xxx.yyy.zzz.com').group()
print(g3)
# 输出结果:'nobody@www.xxx.yyy.zzz.com'

m = re.match('\w\w\w-\d\d\d', 'abc-123')
if m is not None:
    print(m.group())
# 输出结果:'abc-123'

m = re.match('\w\w\w-\d\d\d', 'abc-xyz')
if m is not None:
    print(m.group())
# 无输出结果:

m = re.match('(\w\w\w)-(\d\d\d)', 'abc-123')
print(m.group()) # 完整匹配
# 输出结果:'abc-123'

print(m.group(1))  # 子组 1
# 输出结果:'abc'

print(m.group(2))  # 子组 2
# 输出结果:'123'

print(m.groups())  # 全部子组
# 输出结果:('abc', '123')

m = re.match('ab', 'ab') # 没有子组
print(m.group()) # 完整匹配
# 输出结果:'ab'

print(m.groups()) # 所有子组
# 输出结果:()

m = re.match('(ab)', 'ab') # 一个子组
print(m.group()) # 完整匹配
# 输出结果:'ab'

print(m.group(1)) # 子组 1
# 输出结果:'ab'

print(m.groups()) # 全部子组
# 输出结果:('ab',)

m = re.match('(a)(b)', 'ab') # 两个子组
print(m.group()) # 完整匹配
# 输出结果:'ab'

print(m.group(1)) # 子组 1
# 输出结果:'a'

print(m.group(2)) # 子组 2
# 输出结果:'b'

print(m.groups()) # 所有子组
# 输出结果:('a', 'b')

m = re.match('(a(b))', 'ab') # 两个子组
print(m.group()) # 完整匹配
# 输出结果:'ab'

print(m.group(1)) # 子组 1
# 输出结果:'ab'

print(m.group(2)) # 子组 2
# 输出结果:'b'

print(m.groups()) # 所有子组
# 输出结果:('ab', 'b')

3.11、匹配字符串的起始和结尾以及单词边界


m = re.search('^The', 'The end.') # 匹配
if m is not None:
    print(m.group())
# 输出结果:'The'

m = re.search('^The', 'end. The') # 不作为起始
if m is not None:
    print(m.group())
# 无输出结果

m = re.search(r'\bthe', 'bite the dog') # 在边界
if m is not None:
    print(m.group())
# 输出结果:'the'

m = re.search(r'\bthe', 'bitethe dog') # 有边界
if m is not None:
    print(m.group())
# 无输出结果

m = re.search(r'\Bthe', 'bitethe dog') # 没有边界
if m is not None:
    print(m.group())
# 输出结果:'the'

3.12、扩展符号

(?iLmsux) 系列选项
可以直接在正则表达式里面指定一个或者多个标记,而不是通过 compile()或者其他 re 模块函数。

扩展符号描述
(?i)等同于re.I/IGNORECASE,忽略大小写
(?m)等同于re.M/MULTILINE ,在目标字符串中实现跨行搜索
(?s)等同于re.S/DOTALL,点号(.)能够用来表示\n 符号(反之其通常用于表示除了\n 之外的全部字符)
(?x)等同于re.X/VERBOSE,通过抑制在正则表达式中使用空白符(除了在字符类中或者在反斜线转义中)来创建更易读的正则表达式
(?:…)通过使用该符号,可以对部分正则表达式进行分组,但是并不会保存该分组用于后续的检索或者应用
(?P)使用一个名称标识符而不是使用从 1 开始增加到 N 的增量数字来保存匹配,如果使用数字来保存匹配结果,我们就可以通过使用\1,\2 …,\N \来检索
(?P=name)可以在一个相同的正则表达式中重用模式,而不必稍后再次在(相同)正则表达式中指定相同的模式
(?=…)在目标字符串中实现一个前视匹配,正向前视断言
(?!…)在目标字符串中实现一个前视匹配, 负向前视断言
import re

r1 = re.findall(r'(?i)yes', 'yes? Yes. YES!!')
print(r1)
# 输出结果:['yes', 'Yes', 'YES']

r2 = re.findall(r'(?i)th\w+', 'The quickest way is through this tunnel.')
print(r2)
# 输出结果:['The', 'through', 'this']

r3 = re.findall(r'(?im)(^th[\w ]+)', """ 
... This line is the first, 
... another line, 
... that line, it's the best 
... """)
print(r3)
# 输出结果:[]

r4 = re.findall(r'th.+', ''' 
... The first line 
... the second line 
... the third line 
... ''')
print(r4)
# 输出结果:['the second line ', 'the third line ']

r5 = re.findall(r'(?s)th.+', ''' 
... The first line 
... the second line 
... the third line 
... ''')
print(r5)
# 输出结果:['the second line \n... the third line \n... ']

r6 = re.search(r'''(?x) 
\((\d{3})\)     区号 
[ ]            # 空白符 
(\d{3})        # 前缀 
-              # 横线 
(\d{4})        # 终点数字
''', '(800) 555-1212')
if r6 is not None:
    print(r6.group())
# 无输出结果

r7 = re.findall(r'http://(?:\w+\.)*(\w+\.com)', 'http://google.com http://www.google.com http://code.google.com')
print(r7)
# 输出结果:['google.com', 'google.com', 'google.com']

r8 = re.search(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})', '(800) 555-1212').groupdict()
print(r8)
# 输出结果:{'areacode': '800', 'prefix': '555'}

# 使用一个类似风格的\g<name>来检索它们
r9 = re.sub(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})', '(\g<areacode>) \g<prefix>-xxxx', '(800) 555-1212')
print(r9)
# 输出结果:(800) 555-xxxx

# 压缩版
r10 = bool(re.match(
    r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?P<number>\d{4}) (?P=areacode)-(?P=prefix)-(?P=number)(?P=areacode)(?P=prefix)(?P=number)',
    '(800) 555-1212 800-555-1212 18005551212'))
print(r10)
# 输出结果:False

# 普通版
r11 = bool(re.match(r'''(?x) 
# match (800) 555-1212, save areacode, prefix, no. 
\((?P<areacode>\d{3})\)[ ](?P<prefix>\d{3})-(?P<number>\d{4}) 
# space 
[ ] 
# match 800-555-1212 
(?P=areacode)-(?P=prefix)-(?P=number) 
# space 
[ ] 
# match 18005551212 
1(?P=areacode)(?P=prefix)(?P=number) 
''', '(800) 555-1212 800-555-1212 18005551212'))
print(r11)
# 输出结果:True

r12 = re.findall(r'\w+(?= van Rossum)', ''' 
Guido van Rossum 
Tim Peters 
Alex Martelli 
Just van Rossum 
Raymond Hettinger 
... ''')
print(r12)
# 输出结果:['Guido', 'Just']

r13 = re.findall(r'(?m)^\s+(?!noreply|postmaster)(\w+)', ''' 
sales@phptr.com 
postmaster@phptr.com 
eng@phptr.com 
noreply@phptr.com 
admin@phptr.com 
... ''')
print(r13)
# 输出结果:['sales']

r14 = ['%s@aw.com' % e.group(1) for e in re.finditer(r'(?m)^\s+(?!noreply|postmaster)(\w+)', ''' 
sales@phptr.com 
postmaster@phptr.com 
eng@phptr.com 
noreply@phptr.com 
admin@phptr.com 
... ''')]
print(r14)
# 输出结果:['sales@aw.com']
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值