regular expression

跟风学正则の笔记 测试工具

what is Regular Expression

正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。

How

From LiaoXueFeng

Simple Introduction

在正则表达式中,如果直接给出字符,就是精确匹配。

\d可以匹配一个数字,\w可以匹配一个字母或数字,所以:

  • '00\d'可以匹配'007',但无法匹配'00A'

.可以匹配任意字符,所以:

  • 'py.'可以匹配'pyc''pyo''py!'

要匹配变长的字符,在正则表达式中,

  1. *表示任意个字符(包括0个)
  2. +表示至少一个字符
  3. ?表示0个或1个字符
  4. {n}表示n个字符,用{n,m}表示n-m个字符:

A|B可以匹配A或B,所以(P|p)ython可以匹配'Python'或者'python'

^表示行的开头,^\d表示必须以数字开头。

$表示行的结束,\d$表示必须以数字结束。

如果你想查找元字符本身的话,比如你查找.,或者,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使用\来取消这些字符的特殊意义。因此,你应该使用.和\。当然,要查找\本身,你也得用\.

例如:deerchao\.net匹配deerchao.net,C:\\Windows匹配C:\Windows。

In Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import re
# 从头找,找到了返回对象,找不到返回none
re.match(p,text)
# 不是从第一个字符开始找
obj = re.search(p,text)
obj.start(),obj.end(),obj.group()

# 找到多个对象
re.findall(p,text)
# 找到后把字符串分隔开
re.split(p,text)
# p替换成s
re.sub(p,s,text)

^ 字符串开头
\b 单词开头\末尾
\w 数字字母
\S 不是空格
+ == {1,}
? 非贪婪模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import re

s = r'ABC\-001'

ans = re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
# <_sre.SRE_Match object; span=(0, 9), match='010-12345'>
# print(ans.group(0)

ans = re.match(r'^\d{3}\-\d{3,8}$', '010 12345')
#none

re.split(r'\s+', 'a b c')
# +匹配前面的子表达式一次或多次
# \s匹配任何空白字符
# ['a', 'b', 'c']

ans = re.split(r'[\s\,]+', 'a,b, c d')
# \将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符
# ['a', 'b', 'c', 'd']

# 分组
m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
# <_sre.SRE_Match object; span=(0, 9), match='010-12345'>
m.group(0)
# '010-12345'
m.group(1)
# '010'
m.group(2)
# '12345'

# 贪婪匹配
re.match(r'^(\d+)(0*)$', '102300').groups()
# + 匹配前面的子表达式一次或多次。
# * 匹配前面的子表达式零次或多次
# ('102300', '')
# 非贪婪匹配
re.match(r'^(\d+?)(0*)$', '102300').groups()
#? 匹配前面的子表达式零次或一次。
#('1023', '00')

print(ans)

#预编译
# 编译:
re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
re_telephone.match('010-12345').groups()
#('010', '12345')

字符类型

  1. 普通字符

  2. 非打印字符

    | char | description |
    | —- | ———————————- |
    | \cx | 匹配由x指明的控制字符。 |
    | \f | 匹配一个换页符。等价于 \x0c 和 \cL |
    | \n | 匹配一个换行符。等价于 \x0a 和 \cJ |
    | \r | 匹配一个回车符。等价于 \x0d 和 \cM |
    | \s | 匹配任何空白字符 空格、制表符、换页符==[\f\n\r\t\v]。 |
    | \S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |

  3. 控制字符

    | char | description |
    | —- | —————————————- |
    | $ | 匹配输入字符串的结尾位置。 |
    | ( ) | 标记一个子表达式的开始和结束位置。 |
    | | 匹配前面的子表达式零次或多次。要匹配 字符,请使用 *。 |
    | + | 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。 |
    | . | 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。 |
    | [ | 标记一个中括号表达式的开始。要匹配 [,请使用 [。 |
    | ? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。 |
    |  | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配换行符。序列 ‘\‘ 匹配 “\”,而 ‘(‘ 则匹配 “(“。 |
    | ^ | 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。 |
    | { | 标记限定符表达式的开始。要匹配 {,请使用 {。 |
    | | | 指明两项之间的一个选择。要匹配 |,请使用 |。 |
    | | |

  4. 限定字符

char description
* 匹配前面的子表达式零次或多次。例如,zo 能匹配 “z” 以及 “zoo”。 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,”do(es)?” 可以匹配 “do” 或 “does” 中的”do” 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,’o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。’o{1,}’ 等价于 ‘o+’。’o{0,}’ 则等价于 ‘o*’。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,”o{1,3}” 将匹配 “fooooood” 中的前三个 o。’o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。

示例

\d{3}\s+\d{3,8}

  1. \d{3}表示匹配3个数字,例如'010'
  2. \s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格,例如匹配' '' '等;
  3. \d{3,8}表示3-8个数字,例如'1234567'

\(?0\d{2}[) -]?\d{8}。

“(”和“)”也是元字符,后面的分组节里会提到,所以在这里需要使用转义

这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。我们对它进行一些分析吧:首先是一个转义字符(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。

正则表达式 描述
/\b([a-z]+) \1\b/gi 一个单词连续出现的位置。
/(\w+):\/\/([^/:]+)(:\d)?([^# ])/ 将一个URL解析为协议、域、端口及相对路径。
/^(?:Chapter\ Section) [1-9][0-9]{0,1}$/ 定位章节的位置。
/[-a-z]/ A至z共26个字母再加一个-号。
/ter\b/ 可匹配chapter,而不能匹配terminal。
/\Bapt/ 可匹配chapter,而不能匹配aptitude。
/Windows(?=95 \ 98 \ NT )/ 可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后,从Windows后面开始进行下一次的检索匹配。
/^\s*$/ 匹配空行。
/\d{2}-\d{5}/ 验证由两位数字、一个连字符再加 5 位数字组成的 ID 号。
/<\s(\S+)(\s[^>])?>[\s\S]<\s\/\1\s*>/ 匹配 HTML 标记。

Exercise

email

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import re
# email

patten = 'bill.gates@microsoft.com'
r = r'^(\w*)\.?(\w*)@(\w+).(\w+)'

print(re.match(r,patten).groups())

r1 = r'(<\w+\s\w+>)\s*(\w*)\.?(\w*)@(\w+).(\w+)'
patten1 = '<Tom Paris> tom@voyager.org'
print(re.match(r1,patten).groups())

# 别人的
re_email = re.match(r'^(\w+\.\w+|\w+)(\@\w+\.com)$','bill.a@microsoft.com')
print(re_email.groups())

参考资料

Runoob 30min 廖雪峰 官方文档 python正则 路人甲

文章目录
  1. 1. what is Regular Expression
  2. 2. How
    1. 2.1. Simple Introduction
    2. 2.2. In Python
  3. 3. 字符类型
  4. 4. 示例
  5. 5. Exercise
    1. 5.1. email
  6. 6. 参考资料