正则表达式

一、概述

1.概念

  • 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成串”,这个 “规则字符串” 用来表达对字符串的一种过滤逻辑。

2.目的

给定一个正则表达式和另—个字符串,我们可以达到如下的目的:

  • a.给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”);

    例如:邮箱匹配,电话号码匹配

  • b.可以通过正则表达式,从字符串中获取我们想要的特定部分。

    爬虫中解析html数据

3.特点

  • a.灵活性、逻辑性和功能性非常的强;
  • b.可以迅速地用极简单的方式达到字符串的复杂控制。
  • c.对于刚接触的人来说,比较晦涩难懂。

4.学习方法

  • a.做好笔记,不要死记硬背
  • b.大量练习

  python 中通过系统库 re  实现 正则表达式 的所有功能

 

二、正则表达式符号

1.普通字符

下面的案例使用 re 模块的 findall() 函数,函数参考如下:

  • re.findall(pattern, string, flag)
    • 在字符串中找到正则表达式所匹配的所有子串,并返回列表,如果没有找到返回空列表
    • pattern : 正则表达式
    • string:被匹配的字符串
    • flag:标志位用来控制正则表达式匹配方式

 

在最简单的情况下,一个正则表达式看上去就是一个普通的查找串

import re

s1 = "testing123"
s2 = "Testing123"
r = re.findall("test", s1)  # 表示在s1中找到字符串 "test"
print(r)    # 结果:['test']

r1 = re.findall("test", s2)  # 默认情况下大小写敏感
print(r1)    # 结果:[]

r2 = re.findall("test", s2, re.I)  # 修饰符re.I :使匹配对大小写不敏感(ignore)
print(r2)    # 结果:['Test']

 

2.元字符

  • . ” $ * + ?  {  } [ ] | (  )  \ 

2.1通配符.

默认情况下匹配除 \n (换行符)之外的任何单个字符,依次匹配

import re

s1 = "testing123"
s2 = "testing123\n"
s3 = "马保国"

r = re.findall(".", s1)  # 表示在s1中找到字符串 "."
print(r)    # 结果:['t', 'e', 's', 't', 'i', 'n', 'g', '1', '2', '3']

r1 = re.findall(".", s2)  # 除"\n",换行不匹配
print(r1)    # 结果:['t', 'e', 's', 't', 'i', 'n', 'g', '1', '2', '3']

r2 = re.findall("..", s1)  # 匹配两个字符
print(r2)    # 结果:['te', 'st', 'in', 'g1', '23']

r3 = re.findall("马..", s3)  # 匹配两个字符
print(r3)    # 结果:['马保国']

 

修饰符 re.S 使 "." 匹配包括换行在内的所有字符

r4 = re.findall(".", s2, re.S)  # 同 re.DOTALL
print(r4)    # 结果:['t', 'e', 's', 't', 'i', 'n', 'g', '1', '2', '3', '\n']

 

2.2 脱字符 ^

匹配输入字符串的开始位置

s1 = "testing\nTesting\ntest"

r = re.findall("^test", s1)  # 匹配开始是否是 test,默认只匹配单行
print(r)     # 结果:['test']

r_1 = re.findall("t", s1, re.I)  # 所有的 t
print(r_1)       # 结果:['t', 't', 'T', 't', 't', 't']

r_2 = re.findall("^t", s1, re.I)  # 字符串开始的 t
print(r_2)       # 结果:['t']

 

修饰符 re.M 表示 ^ 可以多行匹配

r1 = re.findall("^test", s1, re.M)    # 修饰符re.M:多行匹配
print(r1)     # 结果:['test', 'test']

 

"|"可以将多个修饰符结合起来使用

r2 = re.findall("^test", s1, re.I | re.M)
print(r2)     # 结果:['test', 'Test', 'test']

 

2.3 美元符 $

匹配输入字符串的结束位置

s4 = "testtesting\ntestTesting\ntest"

r = re.findall("testing$", s4)   # 默认匹配单行
print(r)  # 输出:[]

r1 = re.findall("testing$", s4, re.M)    # 修饰符re.M:多行匹配
print(r1)  # 输出:['testing’]

r2 = re.findall("testing$", s4, re.I | re.M)  # 多个修饰符通过oR(|)来指定
print(r2)  # 输出:['testing', 'Testing']

 

2.4 重复元字符 *,+,?

  • * 匹配前面的子表达式任意次
  • +匹配前面的子表达式一次或多次(至少一次)
  • ? 匹配前面的子表达式 0次 或 1次
import re

s1 = "z\nzo\nzoo"

r = re.findall("zo*", s1)  # 匹配o{0,},逗号后不能空格
r1 = re.findall("zo{0,}", s1)

print(r)    # 输出:['z', 'zo', 'zoo’]
print(r1)   # 输出:['z', 'zo', 'zoo']

r2 = re.findall("zo+", s1)  # 匹配o,一次或多次{1,}
r3 = re.findall("zo{1,}", s1)

print(r2)  # 输出:['zo', 'zoo’]
print(r3)   # 输出:['zo', 'zoo']

r4 = re.findall("zo{2}", s1)  # 匹配o,2次
print(r4)  # 输出:['zoo']

s = 'zozozozo!'
r5 = re.findall('(?:zo)+', s)  # 匹配zo,?:zo后面代表整体;没有 ?:只返回括号里面的
print(r5)  # 输出:['zozozozo']

 

2.5 重复元字符 { }

也是控制匹配前面的子表达式次数

import re

s1 = "z\nzo\nzoo"

r = re.findall("zo*", s1)  # 匹配o{0,},逗号后不能空格
r1 = re.findall("zo{0,}", s1)

print(r)    # 输出:['z', 'zo', 'zoo’]
print(r1)   # 输出:['z', 'zo', 'zoo']

r2 = re.findall("zo+", s1)  # 匹配o,一次或多次{1,}
r3 = re.findall("zo{1,}", s1)

print(r2)  # 输出:['zo', 'zoo’]
print(r3)   # 输出:['zo', 'zoo']

r4 = re.findall("zo{2}", s1)  # 匹配o,2次
print(r4)  # 输出:['zoo']

 

2.6字符组  [ ]

表示匹配给出的任意字符

import re

s1 = "test\nTesting\nzoo"

r = re.findall("[eio]", s1)     # 匹配包含的任意字符
print(r)    # 结果:['e', 'e', 'i', 'o', 'o']

r = re.findall("[e-o]", s1)     # 匹配包含的字符范围
print(r)    # 结果:['e', 'e', 'i', 'n', 'g', 'o', 'o']

r1 = re.findall("[0-9]", "ab1234de554")     # 匹配包含的字符范围
print(r1)    # 结果:['1', '2', '3', '4', '5', '5', '4']

r = re.findall("^[eio]", s1, re.M)   # re.M:多行匹配,回忆脱字符,匹配以[eio]开头字符。
print(r)    # 结果:[]

# 脱字符^放到里面组合,表示排除给定字符串
r = re.findall("[^estio]", s1)    # 匹配未包含的任意字符
print(r)    # 结果:['\n', 'T', 'n', 'g', '\n', 'z']

 

2.7选择元字符  |

表示两个表达式选择一个匹配

import re

s1 = "z\nzood \nfood"

r = re.findall("z |food", s1)   # 匹配"z"或"food"
print(r)    # 结果:['food']

r = re.findall("[z|f]ood", s1)  # 匹配"zood"或"food"
print(r)    # 结果:['zood', 'food']

 

2.8分组元字符()

将括号之间的表达式定义为组(group),并且将匹配这个子表达式的字符返回

import re

s1 = "z\nzood\nfood"

r = re.findall("[zlf]o*", s1)   # 不加分组,拿到的引号内正则表达式匹配到的字符
print(r)    # 结果:['z', 'zoo', 'foo']

r = re.findall("[z/f](o*)", s1)     # 加上分组,返回的将是引号内正则表达式匹配到的字符中()中的内容
print(r)    # 结果:['', 'oo', 'oo']

 

2.9 转义元字符  \

用来匹配元字符本身时的转义,和特定字符组成字符串,见预定义字符组

import re

s = '12345@qq.com'

r= re.findall('\.', s)
print(r)    # 结果:['.']

 

2.10 非贷婪模式

在默认情况下,元字符 *, + 和 {(n,m} 会尽可能多的匹配前面的子表达式,这叫贪婪模式。

import re

s = "abcadcaec"

r = re.findall(r"ab.*c", s)     # 贪婪模式,尽可能多的匹配字符(.*或者.+)
print(r)    # 结果:['abcadcaec']

# 当在这些元字符后面加上?时,表示非贪婪,即尽可能少的匹配前面的子表达式
r = re.findall(r"ab.*?c", s)    # 非贪婪模式,尽可能少的匹配字符
print(r)    # 结果:['abc']

r = re.findall('ab.+c', s)    # 贪婪
print(r)    # 结果:['abcadcaec']

r = re.findall('ab.+?c', s)    # 非贪婪
print(r)    # 结果:['abcadc']

r = re.findall('ab.{0,}', s)   # 贪婪
print(r)    # 结果:['abcadcaec']

r= re.findall('ab.{0,}?', s)   # 非贪婪
print(r)    # 结果:['ab']

 

3.预定义字符组

  元字符 \ 与某些字符组合在一起表示特定的匹配含义

3.1 1 \d

匹配单个数字,等价于[0-9]

s = "<a href=' asdf’>1360942725</a>"

a = re.findall('\d', s)
print(a)    # 结果:['1', '3', '6', '0', '9', '4', '2', '7', '2', '5']

a= re.findall('\d+', s)
print(a)    # 结果:['1360942725']

 

3.2 \D

匹配任意单个非数字字符,等价于[0-9]

s = "<a href=' asdf’>1360942725</a>"

a = re.findall('\D', s)
print(a)    # 结果:['<', 'a', ' ', 'h', 'r', 'e', 'f', '=', "'", ' ', 'a', 's', 'd', 'f', '’', '>', '<', '/', 'a', '>']

 

3.3 \s

匹配任意单个空白符,包括空格,制表符(tab),换行符等

s = 'fdfa**68687+我怕n fdgltf_d\n'

a = re.findall('\s', s)
print(a)    # 结果:[' ', '\n']

 

3.4 \S

匹配任何非空白字符

s ='fdfa**68687+我怕n fdg\tf_d\n'

a = re.findall('\S', s)
print(a)    # 结果:['f', 'd', 'f', 'a', '*', '*', '6', '8', '6', '8', '7', '+', '我', '怕', 'n', 'f', 'd', 'g', 'f', '_', 'd']

 

3.5 \w

匹配除符号外的单个字母,数字,下划线或汉字等

s ='fdfa**68687+我怕n fdg\tf_d\n'

a = re.findall("\w", s)
print(a)    # 结果:['f', 'd', 'f', 'a', '6', '8', '6', '8', '7', '我', '怕', 'n', 'f', 'd', 'g', 'f', '_', 'd']

 

3.5 \W

匹配符号

s ='fdfa**68687+我怕n fdg\tf_d\n'

a = re.findall("\w", s)
print(a)    # 结果:['f', 'd', 'f', 'a', '6', '8', '6', '8', '7', '我', '怕', 'n', 'f', 'd', 'g', 'f', '_', 'd']

 

小案例

1.检测邮箱

s = "3003756995@qq.com"

a = re.findall('^\w+@\w+\.com$', s)
if a:
    print('s=是正确格式的邮箱')
else:
    print('s!=不是邮箱地址')

 

2.检测手机号

s = "13854467878"

a = re.findall('^1[3-9]\d{9}$', s)
if a:
    print('手机号格式正确')
else:
    print('手机号不格式正确')

 

4. re 模块常用函数

  1. re.matc
  2. re.search
  3. re.sub
  4. re.findall
  5. re.compile

 

正则表达式是什么

  • 是一串描述文本规则的代码
  • 对文本的搜索、替换、校验,非常复杂的字符
  • 可以进行参数化
  • 任何编程语言基本上都支持正则表达式
  • 绝对大多数的编辑器都是支持正则表达式

1. 可以在下面的网址对正则进行练习

在线正则表达式解析:https://regexper.com/
正则表达式在线测试:https://regex101.com/

2. 匹配单个字符

. :  匹配任意1个字符(除了\n)

[ ] :  匹配【】中列举的字符

\d :  匹配数字,0-9

\D :  匹配非数字,即不是数字

\s :  匹配空白,即 空格,tab 键

\S :  匹配非空白

\w :  匹配单词字符,即a-z、A-Z、0-9、-

\W  :  匹配非单词字符

3. 匹配多个字符

*  :  匹配前一个字符出现0 次或者 无限次,即可有可无

+  :  匹配前一个字符出现1次 或者 无限次,即至少有1 次

?  :  匹配前一个字符出现 1 次 或者0 次,即 要么1次,要么没有

{m}  :  匹配前一个字符出现 m 次

{m,n}  :  匹配前一个字符出现 从m到n次;例如:/o{2,3}

 

 

 

 

 

 

 

*******请大家尊重原创,如要转载,请注明出处:转载自:https://www.cnblogs.com/shouhu/   谢谢!!******* 

posted @ 2020-01-08 10:34  守护往昔  阅读(390)  评论(0编辑  收藏  举报