Python正则表达式

目录
〇.前言
一.单字符匹配

二.多字符匹配

三.开始、结束、贪婪和非贪婪

四.转义字符和原生字符串

五.分组
六.re模块常用函数

〇.前言

  • 正则表达式:通俗来说,正则表达式是按照一定的规则,从某个字符串中匹配出想要的数据。标准解释见百度百科
  • 使用方法:import re
  • 常用函数:(在这里先做简单的了解,后面会深入地讲)
    1. match:从开头开始寻找满足条件的字符串
    2. search:从中间查找满足条件的字符串
    3. group分组
    4. findall:查找所有满足条件的
    5. sub:根据规则替换其它字符串
    6. split:根据规则切分字符串
    7. compile:编译正则表达式

一.单字符匹配

1.匹配某个字符串

  • 我们在这里需要使用函数match来操作:
    re.match(查找格式, 查找的字符串)
import re

text = 'abc'
# 从头查找'a'。若开头不是'a',则查找失败
result = re.match('a', text)  
# match方法返回的是一个对象,我们要用group函数把对象里的数据取出来
print(result)            # <re.Match object; span=(0, 1), match='a'>
print(result.group())    # a
  • match函数只能从开头识别,若开头的字符不匹配,则匹配失败!
    我们将上个例子的查找’a’字符改成查找’b’字符:
import re

text = 'abc'
# 从头查找'b'
result = re.match('b', text)  
print(result)                 # None
# 若继续提取数据,则会报错:
print(result.group())         # AttributeError: 'NoneType' object has no attribute 'group'

2.点("."):匹配任意的字符(除了’\n’)

  • 我们仍然从text字符串中查找,只要字符串非空,就一定能匹配到一个字符。
import re

text = 'abc'
# 从头查找任意字符
result = re.match('.', text)  
print(result)                 # <re.Match object; span=(0, 1), match='a'>
print(result.group())         # a
  • 这次我们将text稍作修改:text = ‘\nabc’
import re

text = '\nabc'
# 从头查找任意字符
result = re.match('.', text)  
# 这时匹配的是'\n',但是'.'无法识别
print(result)                 # None
print(result.group())         # AttributeError: 'NoneType' object has no attribute 'group'

3."\d":匹配任意的数字(0-9)

  • 将text稍作修改:text = “1ab”
import re

text = '1ab'
# 从头查找数字字符
result = re.match('\d', text)  
print(result)            # <re.Match object; span=(0, 1), match='1'>
print(result.group())    # 1

4."\D":匹配任意的非数字

  • 我们的text仍然使用上一个例子中的:text = “1ab”
import re

text = '1ab'
# 从头查找非数字字符
result = re.match('\D', text)
print(result)           # None
print(result.group())   # AttributeError: 'NoneType' object has no attribute 'group'
  • "\D"匹配的是除了数字以外的任何字符
import re

text1 = 'abc'
text2 = '+ab'
# 从头查找非数字字符
result1 = re.match('\D', text1)
result2 = re.match('\D', text2)
print(result1.group())    # a
print(result2.group())    # +

5."\s":匹配空白字符(包括:\n, \t, \r, 空格)

  • 空白符在打印区看不到,若没报错则为查找成功。为了能够加强视觉效果,我们的例子这样做:
import re

text = '\nabc'
# 加强视觉效果
print('~'*10)
# 从头查找空白字符
result = re.match('\s', text)
print(result.group())
# 加强视觉效果
print('~'*10)
# ~~~~~~~~~~
# 
# 
# ~~~~~~~~~~

6."\S":匹配非空白符

  • 与"\D"的概念相似,\D匹配除了空白符以外的所有字符
import re

text = 'abc'
# 从头查找非空白字符
result = re.match('\S', text)
print(result.group())   # a

7."\w":匹配字母(a-z、A-Z)数字和下划线

  • "\w"所查找的范围相对较为广泛,匹配的规则很像Python中定义变量的规则
import re

text1 = 'abc'
text2 = '23a'
text3 = '_ab'
text4 = '+ab'
result1 = re.match('\w', text1)
result2 = re.match('\w', text2)
result3 = re.match('\w', text3)
# '\w'只限于数字、字母和下划线
result4 = re.match('\w', text4)
print(result1.group())    # a
print(result2.group())    # 2
print(result3.group())    # _
print(result4.group())    # AttributeError: 'NoneType' object has no attribute 'group'

8."\W":匹配的与"\w"相反

  • 用法和前面的很相似,在这里不做过多赘述

9."[]"组合:只要满足括号中的某一项都算匹配成功

  • "[]"的使用方法较灵活,所以使用范围要广泛很多:
import re

text1 = 'abc'
text2 = '23a'
text3 = '_ab'
text4 = '+ab'
rule = '[ac2_+]'
result1 = re.match(rule, text1)
result2 = re.match(rule, text2)
result3 = re.match(rule, text3)
result4 = re.match(rule, text4)
print(result1.group())    # a
print(result2.group())    # 2
print(result3.group())    # _
print(result4.group())    # +
  • “\d”, “\w"都可以用这种方式来表示(连续的数字或字母,可以写出开头和结尾,中间内容用”-"代替)

\d:[0-9]
\w:[a-zA-Z0-9]

二.多字符匹配

  • 先对符号做简单说明:
字符匹配
*匹配前一个字符0次或者无限次
+匹配前一个字符1次或者无限次
?匹配前一个字符0次或者1次
{m} / {m, n}匹配一个字符m次或者n次
*? / +? / ??非贪婪模式(在此处略,详细内容见第三部分)

1."*":匹配任意多个字符

  • 可以匹配字符串中所有符合条件的字符
import re

text = 'Hello World'
# 匹配以字母开头的字符串,任意长度(碰到不合规则的字符就停下)
result1 = re.match('[a-zA-Z]*', text)
# " "是个不合规则的字符,则result1为" "之前的字符串
print(result1.group())    # Hello

result2 = re.match('\d*', text)
# 没有数字
print(result2)            # <re.Match object; span=(0, 0), match=''>
print(result2.group())    # 空(0个字符)

2."+":匹配1个或多个字符

  • 至少要匹配一个字符
    我们仍然以刚刚的例子做示范:
import re

text = 'Hello World'
result = re.match('[a-zA-Z]+', text)
print(result.group())     # Hello
result2 = re.match('\d+', text)
# 没有数字
print(result2)            # None
print(result2.group())    # AttributeError: 'NoneType' object has no attribute 'group'

3."?":匹配0个或1个字符

  • "?"要在英文输入法下输入。其用法与前两个相似,我们直接上代码:
import re

text = 'Hello World'
result = re.match('[a-zA-Z]?', text)
print(result.group())     # H(1个字符)
result2 = re.match('\d?', text)
# 没有数字
print(result2)            # <re.Match object; span=(0, 0), match=''>
print(result2.group())    # 空(0个字符)

4."{m}":匹配m个字符

  • 前几个都是正则表达式提前内置好的,如果我只想匹配2个或几个字符串的时候,就需要"{m}"来实现:
import re

text = 'Hello World'
# 匹配三个字符
result = re.match('[a-zA-Z]{3}', text)
print(result.group())     # Hel

三.开始、结束、贪婪和非贪婪

  • 熟悉函数:search()
    search的用法与match的用法相似,re.search(查找条件,被查找的字符串)。与match不同的是:search函数是在字符串中匹配查找。我们来做个示范:
import re

text = 'abc'
# 从字符串中查找'b'。只要字符串中存在,则查找成功
result = re.search('b', text)
print(result)            # <re.Match object; span=(1, 2), match='b'>
print(result.group())    # b

1."^":以……开头

  • "^"的功能可以说与match函数相同。若开头的字符未匹配,则匹配失败。我们使用刚刚了解到的search函数来举例:
import re

text = 'Hello World'
# 从字符串中查找'World'。
result = re.search('World', text)
print(result)            # <re.Match object; span=(6, 11), match='World'>
print(result.group())    # World
# 使用"^"来规定查找规则:开头是"World"的字符串中,查找"World"
result2 = re.search('^World', text)
print(result2)            # None
print(result2.group())    # AttributeError: 'NoneType' object has no attribute 'group'

2."$":以……结尾

  • 和"^"的用法一样,只是要求的位置不同。直接上代码:
import re

text = 'Hello World'
# 使用"$"来规定查找规则:结尾是"World"的字符串中,查找"World"
# "^"是”以……开头“,所以符号在前;"$"是“以……结尾”,所以符号在后
result2 = re.search('World$', text)
print(result2)            # <re.Match object; span=(6, 11), match='World'>
print(result2.group())    # World

3."|":匹配多个字符串的或者表达法

  • 当我们匹配单一字符时,我们可以用"[]“的方法来进行选择式查找;若我们的需求是固定的字符串,那么我们就应该用”|"的方式去匹配:
import re

text = input('请输入网址:')
# 因为我们不知道用户会输入以http、https、htp三种中的哪一种来开头,所以我们使用"|"
# 对选择的整个对象用括号"()"括起来
result = re.match('(http|https|htp)://\S+', text)
print(result)            # <re.Match object; span=(0, 46), match='https://editor.csdn.net'>
print(result.group())    # https://editor.csdn.net

4.贪婪和非贪婪

  • 贪婪模式,总是尝试匹配尽可能多的字符;非贪婪模式则相反,总是尝试匹配尽可能少的字符。
  • 之前的查找匹配中,我们都是使用的贪婪模式:匹配到不能匹配为止(匹配到的字符串尽可能的长)。
  • 若现在出现了这样一个字符串:text = "name(Wang Qiang), subject(Python)"我们想提取出姓名,按照之前的经验,我们应该这样写:
import re

text = "name(WangQiang),subject(Python)"
result = re.search('\(.+\)', text)  # 左括号和右括号前面的"\"是转义字符
print(result.group())    # (WangQiang),subject(Python)
  • 但是输出的却是将最左边与最右边的括号中间的内容都选中了,这就不符合我们的要求。那我们如何实现选择在第一个右括号前停下呢?
非贪婪模式的常用形式:"+?":按最少的标准来查找
  • 对于上一个问题,我们就有了解决的方案:
import re

text = "name(WangQiang),subject(Python)"
# "+?"非贪婪模式
result = re.search('\(.+?\)', text)
print(result.group())    # (WangQiang)

四.转义字符和原生字符串

1.Python中的转义字符

  • 通俗来讲,就是以"\"开头的字符
转义字符说明
\n换行符,将光标位置移到下一行开头。
\r回车符,将光标位置移到本行开头。
\t水平制表符,也即 Tab 键,一般相当于四个空格。
\a蜂鸣器响铃。注意不是喇叭发声,现在的计算机很多都不带蜂鸣器了,所以响铃不一定有效。
\b退格(Backspace),将光标位置移到前一列。
\\反斜线
\’单引号
\"双引号
\在字符串行尾的续行符,即一行未完,转到下一行继续写。

2.正则表达式中的转义字符

  • 正则表达式中有时候我们会匹配$、{、^等一些符号,这些在正则表达式中已经赋予了意义,于是若想匹配,则需要在符号前加"\"
符号说明
$匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 \$
( )标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用\(,\)
*匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*
+匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+
.匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \.
[ ]标记一个中括号表达式的开始。要匹配 [,请使用 \[,\]
?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?
^匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^
{ }标记限定符表达式的开始。要匹配 {,请使用 \{,\}
|指明两项之间的一个选择。要匹配 |,请使用 \|
  • 举例之前,先了解一个新函数:findall(查找条件,被查找的字符串)
    findall()查找字符串中所有符合规则的字符串。和前两个函数不同之处在于:findall函数返回的是列表,所以不需要group()函数来将数据取出。
  • 我们来用代码举例:
import re

text = "Apple price is $10, and banana price is $20."
# 将价格全部找出来
result = re.findall('\$\d+', text)
print(result)    # ['$10', '$20']

3.原生字符串

  • 这里有一个字符串:text = “\cba c”
    我想取出"\c",按照之前的经验,我们应该这样写:
import re

text = "\cba c"
result = re.match('\c', text)
print(result)  # re.error: bad escape \c at position 0
  • 但是我们会发现编译器报了一个好长的错。原因是,在正则表达式规则中,""会和后面的字母结合起来形成一个具有特殊意义的符号。而"\c"在编译器读取之后发现它并没有预先定义好,所以报错。
  • 那我们试试用转义字符的使用方法,用两个下划线可不可以?
import re

text = "\cba c"
result = re.match('\\c', text)
print(result)  # re.error: bad escape \c at position 0
  • 这次仍然报了一个相同的错误。我们结合Python中的转义字符规则与正则表达式中的转义字符规则发现:"\\“会先通过Python转义字符的规定变成”\",然后再和后面的字符结合。

正则表达式的字符串解析规则:
1.先把这个字符串放在Python语言层面进行分析
2.把Python语言层面分析出的结果再放到正则表达式层间进行解析

  • 为了解决这一个问题,我们必须要保证“经过转义字符的规则后,最后还剩下两个’\’ ”。于是经过思考,我们写出这样一串代码:
import re

text = "\cba c"
result = re.match('\\\\c', text)
print(result.group())  # \c
  • 也就是说,我们要通过两次Python转化,将四个"\“变成两个”\",再经过正则表达式中的转义字符规则,将两个"\“变成一个”\",进而实现需求。但是这种方法过于繁琐,稍有不慎便会出错。
原生字符串:避开Python层面的解析,写入的字符串直接进行正则表达式层面的解析
  • 使用方法:在字符串前加字母r
import re

text = "\cba c"
# 将价格全部找出来
result = re.match(r'\\c', text)
print(result.group())  # \c

五.分组

  • 通过分组,取不同部分的字符串
  • 分组方法:括号"()"括起分组的字符串
  • 概念理解起来有些吃力,我们直接上代码:
import re

text = "Apple price is $10, and banana price is $20."
# 将字符串全部取出,并对价格进行分组
result = re.match(r'.+(\$\d+).+(\$\d+).+', text)
print(result.group())   # Apple price is $10, and banana price is $20.
# 分组读取价格
print(result.group(1))  # $10
print(result.group(2))  # $20
  • 分组的角标是存在0的,group(0)是将整体取出
import re

text = "Apple price is $10, and banana price is $20."
# 将字符串全部取出,并对价格进行分组
result = re.match(r'.+(\$\d+).+(\$\d+).+', text)
# 分组读取价格
print(result.group(0))  # Apple price is $10, and banana price is $20.

六.re模块常用函数

1.match/search(查找条件,被查找的字符串)

  • 之前已经用过很多次,在此不做过多赘述

2.findall(查找条件,被查找的字符串):查找所有满足的字符串

import re

text = "Apple price is $10, and banana price is $20."
# 将价格全部找出来
result = re.findall('\$\d+', text)
print(result)    # ['$10', '$20']

3.sub(被替换的字符串, 想替换的字符串, 被查找的字符串):根据规则替换其它字符串

  • sub方法比Python中的replace方法更强大,替换范围更广泛。替换之后返回替换好的字符串
  • 例:将字符串中的空格替换成"-"
import re

text = "Apple price is $10 and banana price is $20"
result = re.sub(r' ', '_', text)
print(result)  # Apple_price_is_$10_and_banana_price_is_$20

4.split(查找条件, 被查找的字符):根据规则切分字符串

  • 将正则表达式中的查找条件当成分隔符
import re

text = "Apple price is $10, and banana price is $20."
# 将价格作为分隔符
result = re.split(r'\$\d+', text)
print(result)  # ['Apple price is ', ', and banana price is ', '.']

5.compile():编译正则表达式

  • 正则表达式需要经过一层编译才可以运行。之前的代码执行起来都是在执行时先编译,再进行查找操作。用compile的好处在于减少运行时间,适合多次使用同一个规则。
import re

text = "Apple price is $10, and banana price is $20."
# 使用compile进行编译
rule = re.compile('\$\d+')
# 将价格作为分隔符
result = re.findall(rule, text)
print(result)  # ['$10', '$20']
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值