【转载汇集】Python3 正则表达式
一、相关的参考资料:
Python正则表达式指南:
Python3 正则表达式
python正则表达式详解
正则表达式,还不会的同学看过来
二、正则表达式基础
0、如何来的
美国新泽西州的Warren McCulloch和出生在美国底特律的Walter Pitts这两位神经生理方面的科学家,研究出了一种用数学方式来描述神经网络的新方法,他们创造性地将神经系统中的神经元描述成了小而简单的自动控制元,从而作出了一项伟大的工作革新。
1951 年,一位名叫Stephen Kleene的数学科学家,他在Warren McCulloch和Walter Pitts早期工作的基础之上,发表了一篇题目是《神经网事件的表示法》的论文,利用称之为正则集合的数学符号来描述此模型,引入了正则表达式的概念。
后来,人们发现可以将这一工作成果应用于其他方面。Ken Thompson就把这一成果应用于计算搜索算法的一些早期研究,Ken Thompson是 Unix的主要发明人,也就是大名鼎鼎的Unix之父。Unix之父将此符号系统引入编辑器QED,然后是Unix上的编辑器ed,并最终引入grep。
从此,正则表达式被广泛应用开来。
近年来,正则表达式逐渐从模糊而深奥的数学概念,发展成为在计算机各类工具和软件包应用中的主要功能。不仅仅众多UNIX工具支持正则表达式,近二十年来,在WINDOWS的阵营下,正则表达式的思想和应用在大部分 Windows 开发者工具包中得到支持和嵌入应用!从正则式在Microsoft Visual Basic 6 或 Microsoft VBScript到.NET Framework中的探索和发展,WINDOWS系列产品对正则表达式的支持发展到无与伦比的高度,几乎所有 Microsoft 开发者和所有.NET语言都可以使用正则表达式。如果你是一位接触计算机语言的工作者,那么你会在主流操作系统(*nix[Linux, Unix等]、Windows、HP、BeOS等)、主流的开发语言(delphi、Scala、PHP、C#、Java、C++、Objective-c、Swift、VB、Javascript、Ruby以及Python等)、数以亿万计的各种应用软件中,都可以看到正则表达式优美的舞姿。
1、简单介绍
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机编程科学中的一个概念。
正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只在于不同的编程语言实现支持的语法数量不同;但不用担心,不被支持的语法通常是不常用的部分。如果已经在其他语言里使用过正则表达式,只需要简单看一看就可以上手了。
下图展示了使用正则表达式进行匹配的流程:
正则表达式的大致匹配过程是:依次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。如果表达式中有量词或边界,这个过程会稍微有一些不同,但也是很好理解的,看下图中的示例以及自己多使用几次就能明白。
下图列出了Python支持的正则表达式元字符和语法:
2. 数量词的贪婪模式与非贪婪模式
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。
3. 反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
4. 匹配模式
正则表达式提供了一些可用的匹配模式,比如忽略大小写、多行匹配等,这部分内容将在Pattern类的工厂方法re.compile(pattern[, flags])中一起介绍。
三、re模块
1. 开始使用re
Python通过re模块提供对正则表达式的支持。使用re的一般步骤是先将正则表达式的字符串形式编译为Pattern实例,然后使用Pattern实例处理文本并获得匹配结果(一个Match实例),最后使用Match实例获得信息,进行其他的操作。
# encoding: UTF-8import re# 将正则表达式编译成Pattern对象pattern = re.compile(r'hello')# 使用Pattern匹配文本,获得匹配结果,无法匹配时将返回Nonematch = pattern.match('hello world!')if match: #使用Match获得分组信息 print(match.group())### 输出 #### hello
2.re.compile(strPattern[, flag]):
这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。 第二个参数flag是匹配模式,取值可以使用按位或运算符'|'表示同时生效,比如re.I | re.M。另外,你也可以在regex字符串中指定模式,比如re.compile('pattern', re.I | re.M)与re.compile('(?im)pattern')是等价的。
可选值有:· re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
· M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
· S(DOTALL): 点任意匹配模式,改变'.'的行为
· L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
· U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
· X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。以下两个正则表达式是等价的:
a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X)b = re.compile(r"\d+\.\d*")
re提供了众多模块方法用于完成正则表达式的功能。这些方法可以使用Pattern实例的相应方法替代,唯一的好处是少写一行re.compile()代码,但同时也无法复用编译后的Pattern对象。这些方法将在Pattern类的实例方法部分一起介绍。如上面这个例子可以简写为:
m = re.match(r'hello', 'hello world!')print(m.group())### 输出 #### hello
re模块还提供了一个方法escape(string),用于将string中的正则表达式元字符如*/+/?等之前加上转义符再返回,在需要大量匹配元字符时有那么一点用。
3. Match
Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息。
属性:
1. string: 匹配时使用的文本。
2. re: 匹配时使用的Pattern对象。
3. pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
4. endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
5. lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
6. lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
方法:
1. group([group1, …]):
获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。2. groups([default]):
以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。3. groupdict([default]):
返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。4. start([group]):
返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。5. end([group]):
返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。6. span([group]):
返回(start(group), end(group))。7. expand(template):
将匹配到的分组代入template中然后返回。template中可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。\id与\g<id>是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只能使用\g<1>0。import rem = re.match(r'(\w+) (\w+)(?P.*)', 'hello world!')print("m.string:", m.string)print("m.re:", m.re)print("m.pos:", m.pos)print("m.endpos:", m.endpos)print("m.lastindex:", m.lastindex)print("m.lastgroup:", m.lastgroup)print("m.group(1,2):", m.group(1, 2))print("m.groups():", m.groups())print("m.groupdict():", m.groupdict())print("m.start(2):", m.start(2))print("m.end(2):", m.end(2))print("m.span(2):", m.span(2))print(r"m.expand(r'\2 \1\3'):", m.expand(r'\2 \1\3'))### output #### m.string: hello world!# m.re: <_sre.SRE_Pattern object at 0x016E1A38># m.pos: 0# m.endpos: 12# m.lastindex: 3# m.lastgroup: sign# m.group(1,2): ('hello', 'world')# m.groups(): ('hello', 'world', '!')# m.groupdict(): {'sign': '!'}# m.start(2): 6# m.end(2): 11# m.span(2): (6, 11)# m.expand(r'\2 \1\3'): world hello!
4. Pattern
Pattern对象是一个编译好的正则表达式,通过Pattern提供的一系列方法可以对文本进行匹配查找。
Pattern不能直接实例化,必须使用re.compile()进行构造。
Pattern提供了几个可读属性用于获取表达式的相关信息:
1. pattern: 编译时用的表达式字符串。
2. flags: 编译时用的匹配模式。数字形式。
3. groups: 表达式中分组的数量。
4. groupindex: 以表达式中有别名的组的别名为键、以该组对应的编号为值的字典,没有别名的组不包含在内。
import rep = re.compile(r'(\w+) (\w+)(?P.*)', re.DOTALL)print("p.pattern:", p.pattern)print("p.flags:", p.flags)print("p.groups:", p.groups)print("p.groupindex:", p.groupindex)### output #### p.pattern: (\w+) (\w+)(?P .*)# p.flags: 16# p.groups: 3# p.groupindex: {'sign': 3}
实例方法[ | re模块方法]:
1. match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]):
这个方法将从string的pos下标处起尝试匹配pattern;如果pattern结束时仍可匹配,则返回一个Match对象;如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None。
pos和endpos的默认值分别为0和len(string);re.match()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
注意:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'。
示例参见2.1小节。
2. search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]):
这个方法用于查找字符串中可以匹配成功的子串。从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象;若无法匹配,则将pos加1后重新尝试匹配;直到pos=endpos时仍无法匹配则返回None。
pos和endpos的默认值分别为0和len(string));re.search()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
# encoding: UTF-8import re# 将正则表达式编译成Pattern对象pattern = re.compile(r'world')# 使用search()查找匹配的子串,不存在能匹配的子串时将返回None# 这个例子中使用match()无法成功匹配match = pattern.search('hello world!')if match: # 使用Match获得分组信息 print(match.group() )### 输出 #### world
3. split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。
import rep = re.compile(r'\d+')print(p.split('one1two2three3four4'))### output #### ['one', 'two', 'three', 'four', '']
4. findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]):
搜索string,以列表形式返回全部能匹配的子串。
import rep = re.compile(r'\d+')print(p.findall('one1two2three3four4'))### output #### ['1', '2', '3', '4']
5. finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
import rep = re.compile(r'\d+')for m in p.finditer('one1two2three3four4'): print(m.group(),)### output #### 1 2 3 4
6. sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):
使用repl替换string中每一个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count用于指定最多替换次数,不指定时全部替换。
import rep = re.compile(r'(\w+) (\w+)')s = 'i say, hello world!'print(p.sub(r'\2 \1', s))def func(m): return m.group(1).title() + ' ' + m.group(2).title()print(p.sub(func, s))### output #### say i, world hello!# I Say, Hello World!
7. subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]):
返回 (sub(repl, string[, count]), 替换次数)。
import rep = re.compile(r'(\w+) (\w+)')s = 'i say, hello world!'print(p.subn(r'\2 \1', s))def func(m): return m.group(1).title() + ' ' + m.group(2).title()print(p.subn(func, s))### output #### ('say i, world hello!', 2)# ('I Say, Hello World!', 2)
5. re.match函数
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
函数语法:
re.match(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见: |
匹配成功re.match方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
import reprint(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配import reline = "Cats are smarter than dogs"matchObj = re.match( r'(.*) are (.*?) .*', 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!!")
6. re.search方法
re.search 扫描整个字符串并返回第一个成功的匹配。
函数语法:
re.search(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见: |
匹配成功re.search方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
import reprint(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配import reline = "Cats are smarter than dogs";searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)if searchObj: print ("searchObj.group() : ", searchObj.group()) print ("searchObj.group(1) : ", searchObj.group(1)) print ("searchObj.group(2) : ", searchObj.group(2))else: print ("Nothing found!!")
7.re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
import reline = "Cats are smarter than dogs";matchObj = re.match( r'dogs', line, re.M|re.I)if matchObj: print ("match --> matchObj.group() : ", matchObj.group())else: print ("No match!!")matchObj = re.search( r'dogs', line, re.M|re.I)if matchObj: print ("search --> matchObj.group() : ", matchObj.group())else: print ("No match!!")
8. re.sub检索和替换
Python 的re模块提供了re.sub用于替换字符串中的匹配项。
语法:
re.sub(pattern, repl, string, count=0)
参数:
· pattern : 正则中的模式字符串。
· repl : 替换的字符串,也可为一个函数。
· string : 要被查找替换的原始字符串。
· count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
import rephone = "2004-959-559 # 这是一个电话号码"# 删除注释num = re.sub(r'#.*$', "", phone)print ("电话号码 : ", num)# 移除非数字的内容num = re.sub(r'\D', "", phone)print ("电话号码 : ", num)### 输出 #### 电话号码 : 2004-959-559# 电话号码 : 2004959559
· repl 参数是一个函数
以下实例中将字符串中的匹配的数字乘于 2:
import re# 将匹配的数字乘于 2def double(matched): value = int(matched.group('value')) return str(value * 2)s = 'A23G4HFD567'print(re.sub('(?P\d+)', double, s))### 输出 #### A46G8HFD1134
9. re.compile 函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
语法格式为:
re.compile(pattern[, flags])
参数:
· pattern : 一个字符串形式的正则表达式
· flags 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
· re.I 忽略大小写
o re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
o re.M 多行模式
o re.S 即为' . '并且包括换行符在内的任意字符(' . '不包括换行符)
o re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
o re.X 为了增加可读性,忽略空格和' # '后面的注释
import repattern = re.compile(r'\d+') # 用于匹配至少一个数字m = pattern.match('one12twothree34four') # 查找头部,没有匹配print(m)m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配print(m)m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配print(m) # 返回一个 Match 对象)print(m.group(0), m.start(0), m.end(0),m.span(0))# None# None# _sre.SRE_Match object at 0x10a42aac0># 12 3 5 (3, 5)
在上面,当匹配成功时返回一个 Match 对象,其中:
· group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
· start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
· end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
· span([group]) 方法返回 (start(group), end(group))。
import repattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写m = pattern.match('Hello World Wide Web')print(m) # 匹配成功,返回一个 Match 对象print(m.group(0)) # 返回匹配成功的整个子串print(m.span(0)) # 返回匹配成功的整个子串的索引print(m.group(1)) # 返回第一个分组匹配成功的子串print(m.span(1)) # 返回第一个分组匹配成功的子串的索引print(m.group(2)) # 返回第二个分组匹配成功的子串print(m.span(2)) # 返回第二个分组匹配成功的子串print(m.groups()) # 等价于 (m.group(1), m.group(2), ...)print(m.group(3)) # 不存在第三个分组# <_sre.SRE_Match object at 0x10bea83e8># 'Hello World'# (0, 11)# 'Hello'# (0, 5)# 'World'# (6, 11)# ('Hello', 'World')# Traceback (most recent call last):# File "", line 1, in # IndexError: no such group
10. re. findall函数
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配一次 findall 匹配所有。
语法格式为:
findall(string[, pos[, endpos]])
参数:
· string 待匹配的字符串。
· pos 可选参数,指定字符串的起始位置,默认为 0。
· endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
查找字符串中的所有数字:
import repattern = re.compile(r'\d+') # 查找数字result1 = pattern.findall('runoob 123 google 456')result2 = pattern.findall('run88oob123google456', 0, 10)print(result1)print(result2)
11. re. finditer函数
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)
参数:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见: |
import reit = re.finditer(r"\d+","12a32bc43jf3")for match in it: print (match.group() )
12. re. split函数
split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flags=0])
参数:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
maxsplit | 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见: |
re.split('\W+', 'runoob, runoob, runoob.')re.split('(\W+)', ' runoob, runoob, runoob.')re.split('\W+', ' runoob, runoob, runoob.', 1)re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
13. 正则表达式对象
re.RegexObject:re.compile() 返回 RegexObject 对象。
re.MatchObject:group() 返回被 RE 匹配的字符串。
· start() 返回匹配开始的位置
· end() 返回匹配结束的位置
· span() 返回一个元组包含匹配 (开始,结束) 的位置
14. 正则表达式修饰符 - 可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
15. 正则表达式模式
模式字符串使用特殊的语法来表示一个正则表达式:
字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于 \\t )匹配相应的特殊字符。
下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
模式 | 描述 |
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[...] | 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k' |
[^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* | 匹配0个或多个的表达式。 |
re+ | 匹配1个或多个的表达式。 |
re? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{ n} | 匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。 |
re{ n,} | 精确匹配n个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。 |
re{ n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a| b | 匹配a或b |
(re) | G匹配括号内的表达式,也表示一个组 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
(?: re) | 类似 (...), 但是不表示一个组 |
(?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
(?#...) | 注释. |
(?= re) | 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
(?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。 |
(?> re) | 匹配的独立模式,省去回溯。 |
\w | 匹配数字字母下划线 |
\W | 匹配非数字字母下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]。 |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]。 |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。 |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\n, \t, 等。 | 匹配一个换行符。匹配一个制表符, 等 |
\1...\9 | 匹配第n个分组的内容。 |
\10 | 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。 |
16. 正则表达式实例
字符匹配
实例 | 描述 |
python | 匹配 "python". |
字符类
实例 | 描述 |
[Pp]ython | 匹配 "Python" 或 "python" |
rub[ye] | 匹配 "ruby" 或 "rube" |
[aeiou] | 匹配中括号内的任意一个字母 |
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
[^aeiou] | 除了aeiou字母以外的所有字符 |
[^0-9] | 匹配除了数字外的字符 |
特殊字符类
实例 | 描述 |
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 |
\W | 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。 |
17. 分组用法
python 的正则表达式中用小括号 "(" 表示分组,按照每个分组中前半部分出现的顺序 "(" 判定分组的索引,索引从 1 开始,每个分组在访问的时候可以使用索引,也可以使用别名。
s = 'Hello, Mr.Gumby : 2016/10/26'p = re.compile("(?P\w+\.\w+).*?(\d+)(?#comment)")m = p.search(s)# 使用别名访问print(m.group('name'))# output> Mr.Gumby# 使用分组访问print(m.group(2))# output> 2016
有时候可能只是为了把正则表达式分组,而不需要捕获其中的内容,这时候可以使用非捕获分组
s = 'Hello, Mr.Gumby : 2016/10/26'p = re.compile(""" (?: # 非捕获分组标志 用于使用 | (?P\w+\.\w+) | (\d+/) ) """, re.X)m = p.search(s)# 使用非捕获分组# 此分组将不计入 SRE_Pattern 的 分组计数print(p.groups)# output> 2# 不计入 SRE_Match 的分组print(m.groups())# output> ('Mr.Gumby', None)
如果你在写正则的时候需要在正则里面重复书写某个表达式,那么你可以使用正则的引用分组功能,需要注意的是引用的不是前面分组的 正则表达式 而是捕获到的 内容,并且引用的分组不算在分组总数中.
s = 'Hello, Mr.Gumby : 2016/2016/26'p = re.compile(""" (?: # 非捕获分组标志 用于使用 | (?P\w+\.\w+) | (\d+/) ) .*?(?P \d+)/(?P=number)/ """, re.X)m = p.search(s)# 使用引用分组# 此分组将不计入 SRE_Pattern 的 分组计数print(p.groups)# output> 3# 不计入 SRE_Match 的分组print(m.groups())# output> ('Mr.Gumby', None, '2016')# 查看匹配到的字符串print(m.group())# output> Mr.Gumby : 2016/2016/
18. 环视用法
环视还有其他的名字,例如 界定、断言、预搜索等,叫法不一。
环视是一种特殊的正则语法,它匹配的不是字符串,而是 位置,其实就是使用正则来说明这个位置的左右应该是什么或者应该不是什么,然后去寻找这个位置。
环视的语法有四种,见第一小节元字符,基本用法如下。
s = 'Hello, Mr.Gumby : 2016/10/26 Hello,r.Gumby : 2016/10/26'# 不加环视限定print(re.compile("(?P\w+\.\w+)").findall(s))# output> ['Mr.Gumby', 'r.Gumby']# 环视表达式所在位置 左边为 "Hello, "print(re.compile("(?<=Hello, )(?P \w+\.\w+)").findall(s))# output> ['Mr.Gumby']# 环视表达式所在位置 左边不为 ","print(re.compile("(? \w+\.\w+)").findall(s))# output> ['Mr.Gumby']# 环视表达式所在位置 右边为 "M"print(re.compile("(?=M)(?P \w+\.\w+)").findall(s))# output> ['Mr.Gumby']# 环视表达式所在位置 右边不为 rprint(re.compile("(?!r)(?P \w+\.\w+)").findall(s))# output> ['Mr.Gumby']
四、实例分析
1. 分析的实例文件
标准xml文件格式示例:
http://www.0460.com/ http://www.0460.com/view/(d+).html http://m.0460.com/view/${1}.html http://m.0460.com/view/${1}.html
标准txt文件格式示例:
每行两列数据,第一列为PC url pattern,第二列为对应Wap url pattern,两列数据以tab键做分隔。
示例如下:
http://www.0460.com/web/(d+)/(d+)/ http://www.0460.com/web/${1}/${2}/http://www.0460.com/web/(w+).html http://m.0460.com/web/${1}.html
2. 【问题】查找所有industry或者industries
【答案】print(re.findall(r'industr(?:y|ies)', 'Hello industries and industry '))
3. 【问题】查找Windows,后面是95或98或NT
【答案】print(re.findall(r'Windows(?=95|98|NT)', 'Hello Windows95 and Windows3.1'))
4. 【问题】查找Windows,后面非95或98或NT
【答案】print(re.findall(r'Windows(?!95|98|NT)', 'Hello Windows95 and Windows3.1'))
5. 【问题】验证用户名和密码:正确格式:"[A-Z][a-z]_[0-9]"组成,并且第一个字必须为字母6~16位;
【答案】"^[a-zA-Z]w{5,15}$"
6. 【问题】验证电话号码:正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;
【答案】("^(d{3,4}-)d{7,8}$")
7. 验证手机号码;
【答案】"^1[3|4|5|7|8][0-9]{9}$"
8. 验证身份证号;
【答案】(15位):"d{14}[[0-9],0-9xX]",(18位):"d{17}[[0-9],0-9xX]"
9. 验证Email地址;
【答案】"^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$"
10. 只能输入由数字和26个英文字母组成的字符串;
【答案】"^[A-Za-z0-9]+$"
11. 整数或者小数:
【答案】^[0-9]+([.][0-9]+){0,1}$
12. 只能输入数字:。
【答案】"^[0-9]*$"
13. 只能输入n位的数字:。
【答案】"^d{n}$"
14. 只能输入至少n位的数字:。
【答案】"^d{n,}$"
15. 只能输入m~n位的数字:。
【答案】"^d{m,n}$"
16. 只能输入零和非零开头的数字:。
【答案】"^(0|[1-9][0-9]*)$"
17. 只能输入有两位小数的正实数:。
【答案】"^[0-9]+(.[0-9]{2})?$"
18. 只能输入有1~3位小数的正实数:。
【答案】"^[0-9]+(.[0-9]{1,3})?$"
19. 只能输入非零的正整数:。
【答案】"^+?[1-9][0-9]*$"
20. 只能输入非零的负整数:。
【答案】"^-[1-9][0-9]*$"
21. 只能输入长度为3的字符:。
【答案】"^.{3}$"
22. 只能输入由26个英文字母组成的字符串:。
【答案】"^[A-Za-z]+$"
23. 只能输入由26个大写英文字母组成的字符串:。
【答案】"^[A-Z]+$"
24. 只能输入由26个小写英文字母组成的字符串:。
【答案】"^[a-z]+$"
25. 验证是否含有^%&',;=?$"等字符:。
【答案】"[%&',;=?$\^]+"
26. 只能输入汉字:。
【答案】"^[\u4e00-\u9fa5]{0,}$"
27. 验证URL:。
【答案】"^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$"
28. 验证一年的12个月:正确格式为:"01"~"09"和"10"~"12"。
【答案】"^(0?[1-9]|1[0-2])$"
29. 验证一个月的31天:正确格式为;"01"~"09"、"10"~"29"和“30”~“31”。
【答案】"^((0?[1-9])|((1|2)[0-9])|30|31)$"
30. 获取日期正则表达式:
【答案】\d{4}[年|-|.]d{- }[月|-|.]d{-}日?
评注:可用来匹配大多数年月日信息。
31. 匹配双字节字符(包括汉字在内):
【答案】[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
32. 匹配空白行的正则表达式:
【答案】s*
评注:可以用来删除空白行
33. 匹配HTML标记的正则表达式:
【答案】<(S*?)[^>]*>.*?</>|<.*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
34. 匹配首尾空白字符的正则表达式:
【答案】^s*|s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
35. 匹配网址URL的正则表达式:
【答案】[a-zA-z]+://[^s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
36. 匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):
【答案】^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
37. 匹配腾讯QQ号:
【答案】[1-9][0-9]{4,}
评注:腾讯QQ号从10 000 开始
38. 匹配中国邮政编码:
【答案】[1-9]\d{5}(?!d)
评注:中国邮政编码为6位数字
39. 匹配ip地址:。
【答案】([1-9]{1,3}.){3}[1-9]
评注:提取ip地址时有用
40. 匹配MAC地址:
【答案】([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]
41. 匹配HTML标签
【答案】<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[\^'">\s]+))?)+\s*|\s*)\/?>
42. 抽取注释, 移除HMTL中的注释
【答案】<!--(.*?)-->
43. 查找CSS属性
【答案】^\s*[a-zA-Z\-]+\s*[:]{1}\s[a-zA-Z0-9\s.#]+[;]{1}
44. 提取页面超链接
【答案】
(<a\s*(?!.*\brel=)[^>]*)(href="https?:\/\/)((?!(?:(?:www\.)?'.implode('|(?:www\.)?', $follow_list).'))[^"]+)"((?!.*\brel=)[^>]*)(?:[^>]*)>
45. 提取网页图片
【答案】\< *[img][^\\>]*[src] *= *[\"\']{0,1}([^\"\'\ >]*)
46. 抽取网页中的颜色代码
【答案】^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$
47. 验证windows下文件路径和扩展
【答案】^([a-zA-Z]\:|\\)\\([^\\]+\\)*[^\/:*?"<>|]+\.txt(l)?$
48. 提取URL链接
【答案】^(f|ht){1}(tp|tps):\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?
49. 检查URL的前缀, 应用开发中很多时候需要区分请求是HTTPS还是HTTP
【答案】^[a-zA-Z]+:\/\/
50. 校验IP-v6地址
【答案】(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))
51. 校验IP-v4地址
【答案】\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
52. 判断IE的版本
【答案】^.*MSIE [5-8](?:\.[0-9]+)?(?!.*Trident\/[5-9]\.0).*$
53. 国内 13、15、18开头的手机号正则表达式
【答案】^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
54. 金额校验,精确到2位小数。
【答案】^[0-9]+(.[0-9]{2})?$
55. “yyyy-mm-dd“ 格式的日期校验,已考虑平闰年
【答案】
^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$
56. 身份证号码的正则校验。15 或 18位
【答案】
15位:^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$
18位:^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$
57. 同密码一样,下面是E-mail地址合规性的正则检查语句
【答案】[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?
58. 由数字、26个英文字母或下划线组成的字符串
【答案】^\w+$
59. 字符串仅能是中文。
【答案】^[\u4e00-\u9fa5]{0,}$
60. 密码的强度必须是包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间
【答案】^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
61. 匹配双字节字符(包括汉字在内)
【答案】[^\x00-\xff]
62. 校验数字的表达式
【答案】
校验数字的表达式:{
1: 数字:^[0-9]*$
2: n位的数字:^d{n}$
3 :至少n位的数字:^d{n,}$
4: m-n位的数字:^d{m,n}$
5:零和非零开头的数字:^(0|[1-9][0-9]*)$
6:非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
7:带1-2位小数的正数或负数:^(-)?d+(.d{1,2})?$
8:正数、负数、和小数:^(-|+)?d+(.d+)?$
9:有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
10:有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
11:非零的正整数:^[1-9]d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^+?[1-9][0-9]*$
12:非零的负整数:^-[1-9][]0-9"*$ 或 ^-[1-9]d*$
13:非负整数:^d+$ 或 ^[1-9]d*|0$
14:非正整数:^-[1-9]d*|0$ 或 ^((-d+)|(0+))$
15:非负浮点数:^d+(.d+)?$ 或 ^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$
16:非正浮点数:^((-d+(.d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$
17: 正浮点数:^[1-9]d*.d*|0.d*[1-9]d*$ 或 ^(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*))$
18: 负浮点数:^-([1-9]d*.d*|0.d*[1-9]d*)$ 或 ^(-(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*)))$
19: 浮点数:^(-?d+)(.d+)?$ 或 ^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$
}
63. 校验字符的表达式
【答案】
1:汉字:^[\u4e00-\u9fa5]{0,}$
2:英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
3:长度为3-20的所有字符:^.{3,20}$
4:由26个英文字母组成的字符串:^[A-Za-z]+$
5:由26个大写英文字母组成的字符串:^[A-Z]+$
6:由26个小写英文字母组成的字符串:^[a-z]+$
7:由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
8:由数字、26个英文字母或者下划线组成的字符串:^w+$ 或 ^w{3,20}$
9:中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
10:中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
11:可以输入含有^%&',;=?$"等字符:[^%&',;=?$\x22]+
12:禁止输入含有~的字符:[^~\x22]+
64. 特殊需求表达式
【答案】
1: Email地址:^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$
2: 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
3: InternetURL:[a-zA-z]+://[^s]* 或 ^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$
4: 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])d{8}$
5: 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^((d{3,4}-)|d{3.4}-)?d{7,8}$
6: 国内电话号码(0511-4405222、021-87888822):d{3}-d{8}|d{4}-d{7}
7: 身份证号(15位、18位数字):^d{15}|d{18}$
8:短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
9: 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
10: 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]w{5,17}$
11: 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
12: 日期格式:^d{4}-d{1,2}-d{1,2}
13: 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
14: 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
15: 钱的输入格式:
1).有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
2).这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
3).一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
4).这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
5).必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$
6).这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
7).这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
8). 1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
16: xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\.[x|X][m|M][l|L]$
17:中文字符的正则表达式:[\u4e00-\u9fa5]
18:双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
19:空白行的正则表达式: s* (可以用来删除空白行)
20:HTML标记的正则表达式:<(S*?)[^>]*>.*?|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
21:首尾空白字符的正则表达式:^s*|s*$或(^s*)|(s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
22:QQ号:[1-9][0-9]{4,} (QQ号从10000开始)
23:中国邮政编码:[1-9]d{5}(?!d) (中国邮政编码为6位数字)
24:IP地址:d+.d+.d+.d+ (提取IP地址时有用)
25:IP地址:((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))