首页 > 技术文章 > 正则表达式

panghuhu 2021-01-05 18:56 原文

基本匹配

str_temp = 'The cat sat on the Cat'
re.findall("cat", str_temp)
['cat']
str_temp = 'The cat sat on the mat'
re.findall("Cat", str_temp)
[]

元字符

.

元字符 . 可以匹配任意单个字符。它不会匹配换行符和新行的字符。

例如正则表达式 .ar,表示: 任意字符后面跟着一个字母 a, 再后面跟着一个字母 r。

str_temp = 'The car parked in the garage.'
re.findall(".ar", str_temp)
['car', 'par', 'gar']

[ ]

方括号被用于指定字符集。使用字符集内的连字符来指定字符范围。方括号内的字符范围的顺序并不重要。

例如正则表达式 [Tt]he,表示: 大写 T 或小写 t ,后跟字母 h,再后跟字母 e。

str_temp = 'The car parked in the garage.'
re.findall("[Tt]he", str_temp)
['The', 'the']

字符集中的英文句号表示它字面的含义。

正则表达式 ar[.],表示小写字母 a,后面跟着一个字母 r,再后面跟着一个英文句号 . 字符。

str_temp = 'A garage is a good place to park a car.'
re.findall("ar[.]", str_temp)
['ar.']

[^ ]

一般来说插入字符 ^ 表示一个字符串的开始,但是当它在方括号内出现时,它会取消字符集

例如正则表达式 [^c]ar,表示: 除了字母 c 以外的任意字符,后面跟着字符 a, 再后面跟着一个字母 r。

str_temp = 'The car parked in the garage.'
re.findall("[^c]ar", str_temp)
['par', 'gar']

*

  1. 该符号 * 表示匹配上一个匹配规则的零次或多次

正则表达式 a* 表示小写字母 a 可以重复零次或者多次。 但是它如果出现在字符集或者字符类之后,它表示整个字符集的重复。

例如:正则表达式 [a-z]*,表示一行中可以包含任意数量的小写字母。

str_temp = 'The car parked in the garage'
re.findall("[a-z]*", str_temp)
['', 'he', '', 'car', '', 'parked', '', 'in', '', 'the', '', 'garage', '']
  1. 该 * 符号可以与元符号 . 用在一起,用来匹配任意字符串 .*。

  2. 该 * 符号可以与空格符 \s 一起使用,用来匹配一串空格字符

例如:正则表达式 \s*cat\s*,表示:零个或多个空格,后面跟小写字母 c,再后面跟小写字母 a,再再后面跟小写字母 t,后面再跟零个或多个空格。

str_temp = 'The fat cat sat on the cat.'
re.findall("\s*cat\s*", str_temp)
[' cat ', ' cat']

+

该符号 + 匹配上一个字符的一次或多次

例如:正则表达式 c.+t,表示:一个小写字母 c,后跟任意数量的字符,后跟小写字母 t。

str_temp = 'The fat cat sat on the cat.'
re.findall("c.+t", str_temp)
['cat sat on the cat']

?

匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。

在正则表达式中,元字符 ? 用来表示前一个字符是可选的。该符号匹配前一个字符的零次或一次。

例如:正则表达式 [T]?he,表示可选的大写字母 T,后面跟小写字母 h,后跟小写字母 e。

str_temp = 'The car is parked in the garage.'
re.findall("[T]he", str_temp)
['The']
str_temp = 'The car is parked in the garage.'
re.findall("[T]?he", str_temp)
['The', 'he']

{n,m}

花括号,匹配前面字符至少 n 次,但是不超过 m 次

str_temp = 'The number was 9.9997 but we rounded it off to 10.0.'
re.findall("[0-9]{2,3}", str_temp)
['999', '10']
re.findall("[0-9]{2,}", str_temp)
['9997', '10']
re.findall("[0-9]{2}", str_temp)
['99', '97', '10']

(xyz)

字符组,按照确切的顺序匹配字符xyz。

例如:正则表达式 (c|g|p)ar,表示小写字母 c、g 或 p 后面跟字母 a,后跟字母 r。

str_temp = 'The car is parked in the garage.'
re.findall("(c|g|p)ar", str_temp)
['c', 'p', 'g']

|

分支结构,匹配符号之前的字符或后面的字符。

例如:正则表达式 (T|t)he|car,表示大写字母 T 或小写字母 t,后面跟小写字母 h,后跟小写字母 e 或小写字母 c,后跟小写字母 a,后跟小写字母 r。

str_temp = 'The car is parked in the garage.'
re.findall("(T|t)he|car", str_temp)
['T', '', 't']

\

转义符,它可以还原元字符原来的含义,允许你匹配保留字符 [ ] ( ) { } . * + ? ^ $ \ |

正则表达式 (f|c|m)at\.?,表示小写字母 f、c 或者 m 后跟小写字母 a,后跟小写字母 t,后跟可选的 . 字符。

str_temp = 'The fat cat sat on the mat.'
re.findall("(f|c|m)at\.?", str_temp)
['f', 'c', 'm']

^

匹配行的开始

^(T|t)he,这表示: 大写字母 T 或小写字母 t 是输入字符串的起始符号,后面跟着小写字母 h,后跟小写字母 e。

str_temp = 'The car is parked in the garage.'
re.findall("(T|t)he", str_temp)
['T', 't']

$

匹配行的结束 ,例如正则表达式 (at\.)$,表示: 小写字母 a,后跟小写字母 t,后跟一个 . 字符,且这个匹配器必须是字符串的结尾。

str_temp = 'The fat cat. sat. on the mat.'
re.findall("(at\.)", str_temp)
['at.', 'at.', 'at.']
re.findall("(at\.)$", str_temp)
['at.']

简写字符集

.

匹配除换行符以外的任意字符


\w

匹配所有字母和数字的字符: [a-zA-Z0-9_]


\W

匹配非字母和数字的字符: [^\w]


\d

匹配数字: [0-9]


\D

匹配非数字: [^\d]


\s

匹配空格符: [\t\n\f\r\p{Z}]


\S

匹配非空格符: [^\s]


断言

后行断言和先行断言有时候被称为断言,它们是特殊类型的 非捕获组 (用于匹配模式,但不包括在匹配列表中)。

当我们在一种特定模式之前或者之后有这种模式时,会优先使用断言。

?:

非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。

?= 正向先行断言(在...之前)

非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

正向先行断言认为第一部分的表达式必须是先行断言表达式,返回的匹配结果仅包含与第一部分表达式匹配的文本。

要在一个括号内定义一个正向先行断言,在括号中问号和等号是这样使用的 (?=...),先行断言表达式写在括号中的等号后面。

例如:正则表达式 (T|t)he(?=\sfat),表示匹配大写字母 T 或小写字母 t,后面跟字母 h,后跟字母 e。 在括号中,我们定义了正向先行断言,它会引导正则表达式引擎匹配 The 或 the 后面跟着 fat。

str_temp = 'The fat cat. sat. on the mat.'
re.findall("(T|t)he(?=\sfat)", str_temp)
['T']

?! 负向先行断言(不在...之前)

非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。

当我们需要从输入字符串中获取不匹配表达式的内容时,使用负向先行断言。

负向先行断言的定义跟我们定义的正向先行断言一样, 唯一的区别是不是等号 =,我们使用否定符号 !,例如 (?!...)。

例如:正则表达式 (T|t)he(?!\sfat),表示从输入字符串中获取全部 The 或者 the 且不匹配 fat 前面加上一个空格字符。

str_temp = 'The fat cat. sat. on the mat.'
re.findall("(T|t)he(?!\sfat)", str_temp)
['t']

?<= 正向后行断言(在...之后)

非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。

正向后行断言是用于获取在特定模式之前的所有匹配内容,正向后行断言表示为 (?<=...)。

例如:正则表达式 (?<=(T|t)he\s)(fat|mat),表示从输入字符串中获取在单词 The 或 the 之后的所有 fat 和 mat 单词。

str_temp = 'The fat cat. sat. on the mat.'
re.findall("(?<=(T|t)he\s)(fat|mat)", str_temp)
[('T', 'fat'), ('t', 'mat')]
str_temp = 'The fat cat. sat. on the mat.'
re.findall("(?<=[T|t]he\s)(fat|mat)", str_temp)
['fat', 'mat']

?<! 负向后行断言(不在...之后)

非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。这个地方不正确,有问题 .....

负向后行断言是用于获取不在特定模式之前的所有匹配的内容,负向后行断言表示为 (?<!...)。

例如:正则表达式 (?<!(T|t)he\s)(cat),表示在输入字符中获取所有不在 The 或 the 之后的所有单词 cat。

str_temp = 'The cat sat on cat.'
re.findall("(?<!(T|t)he\s)(cat)", str_temp)
[('', 'cat')]
str_temp = 'The cat sat on cat.'
re.findall("(?<![T|t]he\s)(cat)", str_temp)
['cat']

标记

re.I 忽略大小写

i 修饰符用于执行不区分大小写匹配。

例如:正则表达式 /The/gi,表示大写字母 T,后跟小写字母 h,后跟字母 e。 但是在正则匹配结束时 i 标记会告诉正则表达式引擎忽略这种情况。正如你所看到的,我们还使用了 g 标记,因为我们要在整个输入字符串中搜索匹配。

str_temp = 'The fat cat sat on the mat.'
re.findall('The', str_temp)
['The']
str_temp = 'The fat cat sat on the mat.'
re.findall("/The/gi", str_temp)
[]

re.G 全局搜索

g 修饰符用于执行全局匹配 (会查找所有匹配,不会在查找到第一个匹配时就停止)。

例如:正则表达式 /.(at)/g,表示除换行符之外的任意字符,后跟小写字母 a,后跟小写字母 t。 因为我们在正则表达式的末尾使用了 g 标记,它会从整个输入字符串中找到每个匹配项。

str_temp = 'The fat cat sat on the mat.'
re.findall(".(at)", str_temp)
['at', 'at', 'at', 'at']
str_temp = 'The fat cat sat on the mat.'
re.findall("/.(at)/g", str_temp)
[]

re.M 多行模式

m 修饰符被用来执行多行的匹配。正如我们前面讨论过的 (^, $),使用定位符来检查匹配字符是输入字符串开始或者结束。但是我们希望每一行都使用定位符,所以我们就使用 m 修饰符。

例如:正则表达式 /at(.)?$/gm,表示小写字母 a,后跟小写字母 t,匹配除了换行符以外任意字符零次或一次。而且因为 m 标记,现在正则表达式引擎匹配字符串中每一行的末尾。

"/.at(.)?$/" => The fat
                cat sat
                on the mat.
"/.at(.)?$/gm" => The fat
                  cat sat
                  on the mat.
str_temp = """The fat
            cat sat
            on the mat."""
re.findall("/.at(.)?$/", str_temp)
[]
str_temp = """The fat
            cat sat
            on the mat."""
re.findall("/.at(.)?$/gm", str_temp, flags=re.M)
[]

re.L 表示特殊字符集


re.S 表示任意字符

即为 . 并且包括换行符在内的任意字符


re常用函数

re.compile 函数

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象。

re.compile(pattern[, flags])

函数参数说明:

  • pattern : 一个字符串形式的正则表达式
  • flags : 可选,表示匹配模式,比如忽略大小写,多行模式等
str_temp = "Tina is a good girl, she is cool, clever, and so on..."
pt = re.compile(r'\w*oo\w*')
print(pt.findall(str_temp))  # 查找所有包含'oo'的单词
['good', 'cool']

re.findall 函数

遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表。

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

函数参数说明:

  • pattern:一个字符串形式的正则表达式
  • string:
pt = re.compile(r'\d+')
print(pt.findall('o1n2m3k4'))
['1', '2', '3', '4']
tt = "Tina is a good girl, she is cool, clever, and so on..."
pt = re.compile(r'\w*oo\w*')
print(pt.findall(tt))
['good', 'cool']
tt = "Tina is a good girl, she is cool, clever, and so on..."
print(re.findall(r'\w*oo\w', tt))
['good', 'cool']

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 到 所含的小组号。

print(re.match('www', 'www.baidu.com').span())  # 在起始位置匹配
(0, 3)
print(re.match('com', 'www.runoob.com'))  # 不在起始位置匹配
None
line = "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!!")
matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter

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 到 所含的小组号。

  • group()返回被RE匹配的字符串
  • start()返回匹配开始的位置
  • end()返回匹配结束的位置
  • span()返回一个元组包含匹配(开始, 结束)的位置
  • group()返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
print(re.search('www', 'www.runoob.com').group())  # 在起始位置匹配
www
print(re.search('www', 'www.runoob.com').span())  # 在起始位置匹配
(0, 3)
print(re.search('com', 'www.runoob.com').span())  # 不在起始位置匹配
(11, 14)
line = "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!!")
searchObj.group() :  Cats are smarter than dogs
searchObj.group(1) :  Cats
searchObj.group(2) :  smarter
a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0))  # 123abc456,返回整体
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))  # 123
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))  # abc
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(3))  # 456
123abc456
123
abc
456

re.sub 函数

re.sub用于替换字符串中的匹配项。

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

函数参数说明:

  • pattern : 正则中的模式字符串。
  • repl : 替换的字符串,也可为一个函数。
  • string : 要被查找替换的原始字符串。
  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
phone = "2004-959-559 # 这是一个电话号码"

# 删除注释
num = re.sub(r'#.*$', "", phone)
print("电话号码 : ", num)
电话号码 :  2004-959-559 
# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print("电话号码 : ", num)
电话号码 :  2004959559

repl 参数是一个函数

# 以下实例中将字符串中的匹配的数字乘于 2:
# 将匹配的数字乘于 2
def double(matched):
    value = int(matched.group('value'))
    return str(value * 2)

s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
A46G8HFD1134

re.subn 函数

返回替换次数

subn(pattern, repl, string, count=0, flags=0)
print(re.subn('[1-2]', 'A', '123456abcdef'))
print(re.sub("g.t", "have", 'I get A,  I got B ,I gut C'))
print(re.subn("g.t", "have", 'I get A,  I got B ,I gut C'))
('AA3456abcdef', 2)
I have A,  I have B ,I have C
('I have A,  I have B ,I have C', 3)

re.finditer 函数

搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。找到RE匹配的所有子串,并把它们作为一个迭代器返回。

re.finditer(pattern, string, flags=0)
iter = re.finditer(r'\d+', '12 drumm44ers drumming, 11 ... 10 ...')

for i in iter:
    print(i)
    print(i.group())
    print(i.span())
<_sre.SRE_Match object; span=(0, 2), match='12'>
12
(0, 2)
<_sre.SRE_Match object; span=(8, 10), match='44'>
44
(8, 10)
<_sre.SRE_Match object; span=(24, 26), match='11'>
11
(24, 26)
<_sre.SRE_Match object; span=(31, 33), match='10'>
10
(31, 33)

re.split 函数

按照能够匹配的子串将string分割后返回列表。

re.split(pattern, string[maxsplit])
print(re.split('\d+', 'one1two2three3four4five5'))
['one', 'two', 'three', 'four', 'five', '']
print(re.split('a', '1A1a2A3', re.I))
['1A1', '2A3']

输出结果并未能区分大小写

这是因为re.split(pattern,string,maxsplit, flags)默认是四个参数,当我们传入的三个参数的时候,系统会默认re.I是第三个参数,所以就没起作用。如果想让这里的re.I起作用,写成flags = re.I即可。

print(re.split('a', '1A1a2A3', flags=re.I))
['1', '1', '2', '3']

分组(group)

无命名组

最基本的组是由一对圆括号括起来的正则式。

比如上面匹配包夹在字母中间的数字的例子中使用的 (/d+) ,我们再回顾一下这个例子:

s = 'aaa111aaa, bbb222, 333ccc'
re.findall(r'[a-z]+(\d+)[a-z]+', s)
['111']

可以看到 findall 函数只返回了包含在 ’()’ 中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中。

tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt))
print(re.findall(r'(\w)*oo(\w)',tt))   #()表示子表达式 
['good', 'cool']
[('g', 'd'), ('c', 'l')]
m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
print(m.groups())
print(m.group(0))
print(m.group(1))
print(m.group(2))
('010', '12345')
010-12345
010
12345
a = re.search(r'(tina)(fei)haha\2', 'tinafeihahafei tinafeihahatina').group()
print(a)
tinafeihahafei

命名组

# 找出中间夹有数字的字母
s = 'aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'
re.findall(r'([a-z]+)\d+([a-z]+)', s)             
[('aaa', 'aaa'), ('fff', 'ggg')]
# 找出被中间夹有数字的前后同样的字母
s = 'aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'
re.findall(r'(?P<g1>[a-z]+)\d+(?P=g1)', s)  
['aaa']
# 找出前面有字母引导,中间是数字,后面是字母的字符串中的中间的数字和后面的字母
s = 'aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'
re.findall(r'[a-z]+(\d+)([a-z]+)', s)
[('111', 'aaa'), ('777', 'ggg')]

通过序号调用已匹配的组

s = 'aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'
re.findall(r'([a-z]+)\d+\1', s)
['aaa']
# 找出完全对称的 数字-字母-数字-字母-数字 中的数字和字母
s = '111aaa222aaa111 , 333bbb444bb33'
re.findall(r'(\d+)([a-z]+)(\d+)(\2)(\1)', s)
[('111', 'aaa', '222', 'aaa', '111')]

特殊分组

'''
(?P<name>) 分组,除了原有的编号外再指定一个额外的别名	
(?P<id>abc){2}	abcabc

(?P=name) 引用别名为<name>的分组匹配到字符串	
(?P<id>\d)abc(?P=id)	1abc1  5abc5

\<number> 引用编号为<number>的分组匹配到字符串	
(\d)abc\1	 1abc1 5abc5
'''

'\n(?P<name>) 分组,除了原有的编号外再指定一个额外的别名\t\n(?P<id>abc){2}\tabcabc\n\n(?P=name) 引用别名为<name>的分组匹配到字符串\t\n(?P<id>\\d)abc(?P=id)\t1abc1  5abc5\n\n\\<number> 引用编号为<number>的分组匹配到字符串\t\n(\\d)abc\x01\t 1abc1 5abc5\n'

无捕获组

当你要将一部分规则作为一个整体对它进行某些操作,比如指定其重复次数时, 你需要将这部分规则用 ’(?:’ ‘)’ 把它包围起来,而不能仅仅只用一对括号,那样将得到绝对出人意料的结果。

# 例:匹配字符串中重复的 ’ab’
s = "ababab abbabb aabaab"
re.findall(r"\b(?:ab)+\b", s)
['ababab']
# 如果仅使用一对括号,看看会是什么结果:
re.findall( r'\b(ab)+\b' , s )
['ab']

贪婪匹配与非贪婪匹配

*?, +?, ??, {m, n}? 前面的 *, +,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

a = re.findall(r"a(\d+?)", 'a23b')
print(a)
['2']
b = re.findall(r"a(\d+)", 'a23b')
print(b)
['23']
a = re.match('<(.*)>', '<H1>title<H1>').group()
print(a)
<H1>title<H1>
b = re.match('<(.*?)>', '<H1>title<H1>').group()
print(b)
<H1>
a = re.findallr"(a(\d+)b", 'a3333b')
print(a)
[('a3333b', '3333')]
b = re.findall(r"a(\d+?)b", 'a3333b')
print(b)

常用正则表达式

'''
正整数: ^\d+$
负整数: ^-\d+$
电话号码: ^+?[\d\s]{3,}$
电话代码: ^+?[\d\s]+(?[\d\s]{10,}$
整数: ^-?\d+$
用户名: ^[\w\d_.]{4,16}$
字母数字字符: ^[a-zA-Z0-9]*$
带空格的字母数字字符: ^[a-zA-Z0-9 ]*$
密码: ^(?=^.{6,}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$
电子邮件: ^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})*$
IPv4 地址: ^((?:(?: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]?))*$
小写字母: ^([a-z])*$
大写字母: ^([A-Z])*$
网址: ^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$
VISA 信用卡号码: ^(4[0-9]{12}(?:[0-9]{3})?)*$
日期 (MM/DD/YYYY): ^(0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2}$
日期 (YYYY/MM/DD): ^(19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])$
万事达信用卡号码: ^(5[1-5][0-9]{14})*$
'''
'''
汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$或^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$或^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$或^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&’,;=?$\”等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+
'''

推荐阅读