python基础10正则表达式

正则就是字符串处理的瑞士军刀

之前我们是通过if判断来匹配某个字符串,不灵活,太死板了

手机号码匹配,就是有些网站是通过手机号登录的,就是通过这个正则来实现的

电子邮件等应用场景

使用正则就必须使用这个re模块,内置模块,直接导入,不需要下载

re模块核心的函数

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

功能:在整个字符串中查找所有匹配项,返回列表(包含所有匹配结果)

场景:批量提取文本中的目标内容(如所有邮箱、所有数字)

参数详解:

  • pattern 就是匹配的内容,要找的这个内容

  • string 匹配的对象,就是从这个对象里面找我需要的内容,必须是字符串


import  re

s1 = "pythonqwerpython"

result = re.findall("python",s1)
print(result)

# 输出结果为,返回的是一个列表
['python', 'python']


# 匹配失败,返回的是一个空列表

result = re.findall("qc",s1)
print(result)

# 输出结果为
[]

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

功能:从字符串开头匹配正则表达式,仅返回第一个结果

– 只会从最开头开启匹配,只管最前面,匹配的内容在中间也会匹配失败,必须在开头

返回值:匹配成功返回的是一个match对象,失败返回none

match对象常用的方法:

  • span(): 返回匹配的起始和结束的索引,也就是匹配到第一个的切片(元组:(start,end))

  • group(): 返回匹配的整个字符串,就是返回匹配的内容

  • groups(n): 返回第n个分组的内容(n从1开始)


s2 = "pythonqwerpython"

result = re.match("python",s2)

print(result)
# 返回的是一个对象
<re.Match object; span=(0, 6), match='python'>

print(result.span())

# 返回第一个匹配到内容的切片
(0,6)


print(result.group())

# 返回匹配到的内容
python


# match是从开头就开始匹配的,非常精确的匹配

s2 = "qwerpython"  

result = re.match("python",s2)

print(result)

# 输出结果为,没有匹配到,从开头就开始匹配了
None


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

功能:在整个字符串查找第一个匹配项(不限制开头了)

返回值:也是返回一个匹配对象,

区别match, match仅匹配开头,search匹配任意位置,就是从头匹配到尾

方法:

  • span()

  • group()

s4 = "pythonqwertpython"

print(re.search("python",s4))

# 返回一个对象
<re.Match object; span=(0, 6), match='python'>

print(re.search("python",s4).group())

# 返回第一个匹配的到的内容

# 和match最不同的方式,从头开始匹配到尾,输出第一次匹配到的内容

s5 = "qwerpython"
print(re.search("python",s5).group())


# 输出结果为
python

上面匹配的内容都是写死的,因此我们需要使用正则来实现这个灵活性

元字符和量词

元字符是正则表达式的语法符号,量词用于控制字符重复次数,结合使用

  • 查什么

  • 差多少

普通字符(直接匹配)

字母、数字,下划线等普通字符,直接匹配本身

示例;”abc” 匹配 字符串中的”abc”, 123 匹配 123, “_” 匹配 “_”

核心特殊元字符(需要掌握)

元字符

查什么,就是匹配的内容

元字符 含义 示例
. 匹配任意单个字符(除了换行符\n) “a.b”匹配aab,a和b之间任意字符都匹配
^ 匹配字符串开头 ^abc匹配abc123,不匹配xabc
$ 匹配字符串末尾的 n$ 匹配字符串末尾是n的
[] 匹配括号里面任意一个字符,支持范围[a-z],排除[^a-z] “[abc]”匹配a,b,c三个字符
[^] 否定字符集,匹配括号外的任意字符 [^abc] 匹配除了a/b/c外的字符
() 分组:将括号内内容视为整体,可用于提取子串、反向引用 "(ab)+" 匹配 "ab"/"abab""(a)(b)" 可通过 \1/\2 引用
| 或:匹配左右任意一个表达式(优先级较低,需配合分组使用) "a|b" 匹配 "a"/"b""(ab)|(cd)" 匹配 "ab"/"cd"
\ 转义字符:将特殊字符转为普通字符(如 \. 匹配 . "\." 匹配 ".""\*" 匹配 "*""\\n" 匹配换行符
\d 等价于[0-9],匹配任意数字 \d+ 提取字符串中所有数字
\D 等价于[^0-9]匹配非数字 \D+ 提权字符串非数字字符内容
\s 等价于[\t\n\r\f] 匹配看=空白字符(空格,制表符,换行等) \s匹配字符串中的空格
\S 等价于[^\t\n\t\f] 匹配非空白字符 \S 匹配非空白字符
\w 等价于[a-zA-Z0-9_] 匹配字母,数字,下划线 \w+ 匹配单词(含下划线)
\b 匹配单词边界(单词与非单词的分隔)
\B 匹配非单词边界

元字符案例


p1 = "abcdefgqwer"

print(re.findall(".",p1))  # 在整个字符串中匹配任意的单个字符,也就是全部匹配到了

# 返回结果为
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'q', 'w', 'e', 'r']


# 匹配以ab开头的 
s1 = "abcdefabg"
print(re.findall("^ab",s1))

# 返回结果为 
['ab']

# 只匹配bg结尾的字符
print(re.findall(r"bg$",s1))


s2 = "asdqweasdaa"
# 匹配 a-f之间的单个字符
print(re.findall("[a-f]",s2))

# 输出结果为
['a', 'd', 'e', 'a', 'd', 'a', 'a']

s3 = "12345sds23"
# 匹配0-9的单个数字
print(re.findall(r"\d",s3))

# 输出结果为
['1', '2', '3', '4', '5', '2', '3']

# 匹配的是数字和字母的单个字符
print(re.findall(r"\w",s3))

# 输出结果为
['1', '2', '3', '4', '5', 's', 'd', 's', '2', '3']


量词(控制重复次数)

上面的元字符就是告诉我们查什么,都是单个字符的,没有需要查多少次,重复的,且都是定死的,下面学习这个量词,就能查清楚了

量词

查多少次

表示匹配前一个字符出现的次数的控制,支持贪婪和非贪婪模式,是正则的核心特性之一

元字符和量词配合使用,效果最佳

默认所有量词都是贪婪,但是量词后面加上一个? 就是非贪婪,拿到第一个立刻停,绝不多拿

量词类型 语法 贪婪/非贪婪 含义 示例(匹配 a)
零次或多次 * 贪婪 重复 0 次或多次(优先最多) a* 匹配 ""/"a"/"aaa"
零次或多次 *? 非贪婪 重复 0 次或多次(优先最少) a*? 优先匹配 ""
一次或多次 + 贪婪 重复 1 次或多次(优先最多) a+ 匹配 "a"/"aaa"
一次或多次 +? 非贪婪 重复 1 次或多次(优先最少) a+? 优先匹配 "a"
零次或一次 ? 贪婪 重复 0 次或 1 次(优先 1 次) a? 匹配 ""/"a"
零次或一次 ?? 非贪婪 重复 0 次或 1 次(优先 0 次) a?? 优先匹配 ""
精确次数 {n} 无(固定) 必须重复 n 次 a{3} 匹配 "aaa"
范围次数 {m,n} 贪婪 重复 m~n 次(优先 n 次) a{2,4} 匹配 "aa"/"aaa"/"aaaa"
范围次数 {m,n}? 非贪婪 重复 m~n 次(优先 m 次) a{2,4}? 优先匹配 "aa"
最少次数 {m,} 贪婪 至少重复 m 次(无上限,优先最多) a{2,} 匹配 "aa"/"aaa"
最多次数 {,n} 贪婪 最多重复 n 次(0~n 次,优先 n 次) a{,3} 匹配 ""/"a"/"aaa"

量词实战

主要就是这些符号的了解,符号的实战

s1 = "anfaagfa"
# 匹配a字符0次或者多次
print(re.findall(r"a*",s1))

# 输出结果为:
['a', '', '', 'aa', '', '', 'a', '']


s1 = "anfaagfa"
# 那么这个*? 就是非贪婪模式,优先最少,那就是重复0次或者1次,多次最后考虑
print(re.findall(r"a*?",s1))

# 输出结果为:
['', 'a', '', '', '', 'a', '', 'a', '', '', '', 'a', '']


s1 = "anfaagfa"
# a+ 表示匹配a字符1次或者多次
print(re.findall("a+",s1))

# 输出结果:
['a', 'aa', 'a']

# a+? 优先最少,优先1次
print(re.findall("a+?",s1))


s1 = "anfaagfa"
# .* 的意思就是匹配0个或者多个任意的字符
print(re.findall(".*",s1))

# 输出结果为,字符串末尾还有一个空字符串,匹配0个
['anfaagfa', '']

s1 = "anfaagfa"
# 匹配a字符0次或者1次
print(re.findall("a?",s1))

# 输出结果为
['a', '', '', 'a', 'a', '', '', 'a', '']

s1 = "anfaagfa"
# 匹配a字符2次,精确匹配
print(re.findall(r"a{2}",s1))

# 输出结果为:
['aa']

s1 = "anfaagaaafaaaa"
# 匹配a字符1到3次
print(re.findall(r"a{1,3}",s1))

# 输出结果为:
['a', 'aa', 'aaa', 'aaa', 'a']



r核心作用就是让字符串里的\表示普通字符,不被当成转义字符
r”\n”,不能让元字符变成普通,还需要\. 变成普通字符

分组

() 就是创建分组的意思

普通捕获分组

s1 = "hellojava,hellopython"

# findall() 函数默认返回分组内的内容
print(re.findall(r"hello(java|python)",s1))

# 输出结果为
['java', 'python']

非捕获分组

# 继续上面的案例

# 如果想要获取到整个字符串的话,在捕获组里面加上?: 就变成了非捕获组,只返回结果,没有分组信息
s1 = "hellojava,hellopython"
print(re.findall(r"hello(?:java|python)",s1))

# 输出结果为
['hellojava', 'hellopython']

贪婪和非贪婪

默认元字符都是贪婪模式,带有?就是非贪婪,尽可能少一点匹配

s2 = "qweaa1231432fsds"
# 数字至少匹配2次,默认是贪婪模式,就是尽可能多的进行匹配
print(re.findall(r"\d{2,}",s2))

# 输出结果为:
['1231432']

s3 = "aa1212"
print(re.findall(r"aa\d*",s3))

# 输出结果为:
['aa1212']

# 关闭贪婪模式,尽可能少匹配数字
print(re.findall(r"aa\d?",s3))

# 输出结果为:
['aa1']

案例

匹配qq邮箱

qq邮箱规则:

  • 第一个是数字1-9

  • 4-11位

  • @qq.com结尾,写死就行了


s5 = input('请输入qq邮箱:')

print(re.findall(r"^[1-9]\d{4,11}@qq\.com$",s5))

总结

re模块函数总结

re.findall 在整个字符串找到所有匹配的内容,返回一个列表

re.search 在整个字符串找到第一次匹配的内容,返回一个匹配的对象

re.match 从头就开始匹配,不符合就返回none,匹配成功就返回匹配的对象

文章摘自:https://www.cnblogs.com/qylogs/p/20119955