Python标准库之正则表达式(re库)

21
五月
2021

目录

  • 正则表达式
    • 正则表达式语法
      • []
      • +
      • *
      • ?
      • $
      • ^
      • {n}
        • {m,n}
      • \d
      • \D
      • \s
      • \S
      • \w
      • \W
      • \b
      • \B
      • .
      • |
      • ()
    • 模块内容
      • re.match(pattern[过滤模式],string,flags) [从开头匹配]
      • re.search(pattern[过滤模式],string,flags) [从中匹配出]
        • re.search().span()
        • re.search().group()
      • re.findall(pattern,string,flags) [匹配出全部符合要求的字符串]
      • re.sub(pattern,repl,string,counts,flags) [借助修改文本]
      • re.compile(pattern,flags) [将正则表达式字符串编译成字符表达式对象,以便之后的匹配中复用]
    • 修饰符
    • 实战使用

正则表达式

正则表达式(或RE)指定了一组与之匹配的字符串;该模块中的函数可让您检查特定字符串是否与给定的正则表达式匹配(或给定的正则表达式是否与特定的字符串匹配,这取决于同一件事)。

正则表达式语法

pattern[过滤模式]
从string中匹配出符合条件的字符
    1.字符集合
        如:[abcde],[12345]
    2.字符范围
        如:[a-z],[0-9]

    1.+(子表达式后),匹配符合子表达式一次和一次以上的内容 (>=1)
        如:('[0-9]+')
    2.*(子表达式后),匹配符合子表达式零次和零次以上的内容 (>=0)
        如:('[0-9]*')
    3.?(子表达式后),匹配符合子表达式零到一次的内容 (0-1)
        如:('[0-9]?')
    4.$,匹配输入行尾
    5.^,匹配输入行头

    1.{n},匹配n次

    1.\d,匹配一个数字字符,等价于[0-9]
    2.\D,匹配一个非数字字符,等价于[^0-9]
        ^在中括号中代表’非‘
    3.\s,匹配任何不可见字符
        如:空格,制表符,换页符等等
    4.\S,匹配任何可见字符
    5.\w(word),匹配包括下划线的任何单词字符,等价于[A-Za-z0-9_]
    6.\W,匹配任何非单词字符,等价于[^A-Za-z0-9_]
    7.\b,匹配一个单词的边界,也就是指单词和空格间的位置
    8..,匹配除了'\n'和'\r'以外的单个字符

    1.|,将两个匹配条件进行逻辑’或‘运算
    2.(),将(和)之间的表达式定义为“组”(group)

    1.贪婪模式:默认为贪婪模式,匹配尽量多的字符
    2.非贪婪模式:匹配尽量少的字符,在次数限制操作符后面加上'?'转换为非贪婪模式

[]

用于指示一组字符。在一组中:

  • 字符可以单独列出,例如[amk]将匹配’a’,‘m’或’k’。
  • 可以通过给两个字符并用’-‘隔开来表示字符范围,例如[az]可以匹配任何小写ASCII字母,[0-5]
    [0-9]可以匹配所有的两位数字00到59,并且[0-9A-Fa-f]将匹配任何十六进制数字。如果-被转义(例如[a
    -z]),或者如果将其放置为第一个或最后一个字符(例如[-a]或[a-]),则它将匹配文字’-’。
  • 特殊字符在集合内失去其特殊含义。例如,[(+ *)]将匹配任何文字字符’(’,’+’,’*‘或’)’。
  • 集合中也接受\ w或\ S之类的字符类(在下面定义),尽管它们匹配的字符取决于是否启用了ASCII或LOCALE模式。
  • 可以通过补充集合来匹配不在范围内的字符。如果集合中的第一个字符是’^’,则所有不在集合中的字符都将被匹配。例如,[^5]将匹配’5’以外的任何字符,而[^^]将匹配’^'以外的任何字符。 ^如果不是集合中的第一个字符,则没有特殊含义。
  • 要在集合中匹配文字’]’,请在其前面加上反斜杠,或将其放在集合的开头。例如,[()[] {}]和[]()[{}]都将与括号匹配。
  • 将来可能会增加对嵌套集和集操作的支持(如Unicode技术标准#18)。这将更改语法,因此为了便于进行此更改,暂时将在不明确的情况下引发FutureWarning。包括以文字’[‘开头或包含文字字符序列’-’,’&&’,’~~‘和’||'的集合。

为避免警告,请使用反斜杠将其转义。

例如:

message = 'fjlrb2i4t9gjibuspabr'
result = re.search('[abcde]',message)
print(result)
result = re.search('[a-z][a-d]',message)
print(result)
result = re.search('[a-z][0-9]',message)
print(result)
result = re.findall('[a-z][0-9]',message)
print(result)
<_sre.SRE_Match object; span=(4, 5), match='b'>
<_sre.SRE_Match object; span=(3, 5), match='rb'>
<_sre.SRE_Match object; span=(4, 6), match='b2'>
['b2', 'i4', 't9']

+

使结果RE匹配先前RE的1个或多个重复。 ab +将与“ a”匹配,后跟任意非零数目的“ b”; 它不会仅与“ a”匹配。

例如:

message = 'verb very never every'
result = re.findall(r'\w+er\B',message)
print(result)
['ver', 'ver', 'ever']

*

使结果RE与前面的RE的0个或多个重复匹配,并尽可能多地重复。 ab *将匹配“ a”,“ ab”或“ a”,后跟任意数量的“ b”。

例如:

message = 'h25tv988yrgnbn25uyt3n9y2'
result = re.findall('[a-z]*[0-9][a-z]',message)
print(result)
['5t', '8y', '5u', 'yt3n', '9y']

?

使结果RE匹配先前RE的0或1个重复。 ab? 将匹配“ a”或“ ab”。

例如:

message = 'ccc2356145507'
result = re.findall('ccc\d+?',message)
print(result)
['ccc2']

$

匹配字符串的末尾或在字符串末尾的换行符之前,并且在MULTILINE模式下也匹配换行符的前面。 foo同时匹配“ foo”和“ foobar”,而正则表达式foo $仅匹配“ foo”。

例如:

QQ_number = input('请输入您的QQ号码:')
result = re.findall('^[1-9][0-9]{4,10}$',QQ_number)
print(result)
请输入您的QQ号码:123456
['123456']

^

匹配字符串的开头,并且在MULTILINE模式下还匹配每个换行符之后的字符串。

例如:

QQ_number = input('请输入您的QQ号码:')
result = re.findall('^[1-9][0-9]{4,10}$',QQ_number)
print(result)
请输入您的QQ号码:123456
['123456']

{n}

指定应该精确匹配前一个RE的m个副本; 较少的匹配会导致整个RE不匹配。 例如,a {6}将精确匹配六个’a’字符,而不是五个。

例如:

phone_num = input('请输入您的手机号码:')
result = re.match('1[0-9]{10}$',phone_num)
print(result)
result = re.findall('^1[0-9]{10}$',phone_num)
print(result)
请输入您的手机号码:12345678910
<_sre.SRE_Match object; span=(0, 11), match='12345678910'>
['12345678910']

{m,n}

使结果RE匹配先前RE的m到n个重复,并尝试匹配尽可能多的重复。 例如,a {3,5}将匹配3到5个’a’字符。 省略m表示下限为零,省略n表示上限为无限。 例如,a {4,} b将匹配“ aaaab”或一千个“ a”字符,后跟一个“ b”,但不匹配“ aaab”。 逗号可能不会被省略,或者修饰符可能会与前面描述的形式混淆。

例如:

QQ_number = input('请输入您的QQ号码:')
result = re.findall('^[1-9][0-9]{4,10}$',QQ_number)
print(result)
请输入您的QQ号码:2356145507
['2356145507']

\d

对于Unicode(str)模式:

  • 匹配任何Unicode十进制数字(即Unicode字符类别[Nd]中的任何字符)。 其中包括[0-9],以及许多其他数字字符。
    如果使用ASCII标志,则仅匹配[0-9]。

对于8位(字节)模式:

  • 匹配任何十进制数字; 相当于[0-9]。

例如:

message = 'ccc2356145507'
result = re.findall('ccc\d+?',message)
print(result)
['ccc2']

\D

匹配非十进制数字的任何字符。 这与\ d相反。 如果使用ASCII标志,则等效于[^ 0-9]。

\s

对于Unicode(str)模式:

  • 匹配Unicode空格字符(包括[\ t \ n \ r \ f \ v]以及许多其他字符,例如,印刷规则由多种语言规定的不间断空格)。
    如果使用ASCII标志,则仅匹配[\ t \ n \ r \ f \ v]。

对于8位(字节)模式:

  • 匹配ASCII字符集中被视为空格的字符; 等效于[\ t \ n \ r \ f \ v]。

\S

匹配不是空格字符的任何字符。 这与\ s相反。 如果使用了ASCII标志,则等同于[^ \ t \ n \ r \ f \ v]。

\w

对于Unicode(str)模式:

  • 匹配Unicode单词字符; 其中包括可以用任何语言组成的单词的大多数字符,以及数字和下划线。
    如果使用ASCII标志,则仅匹配[a-zA-Z0-9_]。

对于8位(字节)模式:

  • 匹配ASCII字符集中的字母数字字符; 这等效于[a-zA-Z0-9_]。
    如果使用了LOCALE标志,则匹配在当前语言环境和下划线中视为字母数字的字符。

例如:

message = 'verb very never every'
result = re.findall(r'\w+er\B',message)
print(result)
['ver', 'ver', 'ever']

\W

匹配不是单词字符的任何字符。 这与\ w相反。 如果使用ASCII标志,则等同于[^ a-zA-Z0-9_]。 如果使用了LOCALE标志,则匹配在当前语言环境和下划线中都不是字母数字的字符。

\b

匹配空字符串,但仅在单词的开头或结尾处匹配。 单词定义为单词字符序列。 请注意,形式上,\ b定义为\ w和\ W字符之间的边界(反之亦然)或\ w与字符串的开头/结尾之间的边界。 这意味着r’\ bfoo \ b’匹配’foo’,‘foo。’,’(foo)’,‘bar foo baz’,但不匹配’foobar’或’foo3’。

默认情况下,Unicode字母数字是Unicode模式中使用的字母数字,但是可以通过使用ASCII标志进行更改。 如果使用LOCALE标志,则字边界由当前语言环境确定。 在字符范围内,\ b表示退格字符,以与Python的字符串文字兼容。

\B

匹配空字符串,但仅当它不在单词的开头或结尾时才匹配。 这意味着r’py \ B’匹配’python’,‘py3’,‘py2’,但不匹配’py’,'py。‘或’py!’。 \ B与\ b恰好相反,因此Unicode模式中的单词字符是Unicode字母数字或下划线,尽管可以使用ASCII标志来更改。 如果使用LOCALE标志,则字边界由当前语言环境确定。

例如:

message = 'verb very never every'
result = re.findall(r'\w+er\B',message)
print(result)
['ver', 'ver', 'ever']

.

在默认模式下,它匹配换行符以外的任何字符。 如果指定了DOTALL标志,则它匹配包括换行符在内的任何字符。

例如:

message = '<c1>首页</c1>'
result = re.findall(r'^<(\w+)>(.+)</\1>$',message)
print(result)
[('c1', '首页')]

|

A | B,其中A和B可以是任意RE,它创建一个匹配A或B的正则表达式。任意数量的RE可以用’|'分隔。 这样。 也可以在组内使用(请参阅下文)。 扫描目标字符串时,RE用“ |”分隔 从左到右尝试。 当一个模式完全匹配时,该分支被接受。 这意味着,一旦A匹配,即使将产生更长的整体匹配,也不会对其进行进一步测试。 换句话说,“ |” 操作员从不贪婪。 要匹配文字“ |”,请使用\ |,或将其括在字符类中,如[|]所示。

例如:

message = 'verb very never every'
result = re.findall('\w+ev|\w+ry',message)
print(result)
['very', 'nev', 'every']

()

匹配括号内的任何正则表达式,并指示组的开始和结束; 可以在执行匹配后检索组的内容,并且以后可以在字符串中使用\ number特殊序列进行匹配,如下所述。 要匹配文字’(‘或’)’,请使用\(或\),或将它们括在字符类中:[(],[)]。

例如:

message = '<c1>首页</c1>'
result = re.findall(r'^<(\w+)>(.+)</\1>$',message)
print(result)
[('c1', '首页')]

模块内容

  • re.match(pattern[过滤模式],string,flags) [从开头匹配]
  • re.search(pattern[过滤模式],string,flags) [从中匹配出]
  • re.findall(pattern,string,flags) [匹配出全部符合要求的字符串]
  • re.sub(pattern,repl,string,counts,flags) [借助修改文本]
  • re.compile(pattern,flags) [将正则表达式字符串编译成字符表达式对象,以便之后的匹配中复用]

re.match(pattern[过滤模式],string,flags) [从开头匹配]

如果字符串开头的零个或多个字符与正则表达式模式匹配,则返回相应的匹配对象。 如果字符串与模式不匹配,则返回None;否则返回false。

请注意,这与零长度匹配不同。

请注意,即使在MULTILINE模式下,re.match()也只会在字符串的开头而不是在每一行的开头进行匹配。

例如:

message = '钟南山,李兰娟,王辰,黄璐琦,张伯礼,陈薇,乔杰,仝小林,李兰娟'
result = re.match('李兰娟',message)
print(result)
None

re.search(pattern[过滤模式],string,flags) [从中匹配出]

扫描字符串以查找正则表达式模式产生匹配项的第一个位置,然后返回相应的匹配对象。 如果字符串中没有位置与模式匹配,则返回None;

请注意,这与在字符串中的某个点找到零长度匹配不同。

例如:

message = '钟南山,李兰娟,王辰,黄璐琦,张伯礼,陈薇,乔杰,仝小林,李兰娟'
result = re.search('李兰娟',message)
print(result)
<_sre.SRE_Match object; span=(4, 7), match='李兰娟'>

re.search().span()

对于匹配m,返回2元组(m.start(组),m.end(组))。 组默认为零,即整个匹配项。

请注意,如果组对匹配没有帮助,则为(-1,-1)。

例如:

message = '钟南山,李兰娟,王辰,黄璐琦,张伯礼,陈薇,乔杰,仝小林,李兰娟'
result = re.search('李兰娟',message)
print(result.span())
(4, 7)

re.search().group()

返回匹配项的一个或多个子组。 如果有单个参数,则结果为单个字符串;否则,结果为单个字符串。 如果有多个参数,则结果是一个元组,每个参数有一个项目。 没有参数,group1默认为零(返回整个匹配项)。 如果groupN参数为零,则对应的返回值是整个匹配字符串;否则,返回值为0。 如果它在包含范围[1…99]中,则它是与相应括号组匹配的字符串。 如果组号为负或大于模式中定义的组数,则会引发IndexError异常。 如果在不匹配的模式的一部分中包含一个组,则对应的结果为“无”。 如果在多次匹配的模式的一部分中包含一个组,则返回最后一个匹配项。

例如:

message = '钟南山,李兰娟,王辰,黄璐琦,张伯礼,陈薇,乔杰,仝小林,李兰娟'
result = re.search('李兰娟',message)
print(result.group())
李兰娟

re.findall(pattern,string,flags) [匹配出全部符合要求的字符串]

以字符串列表形式返回字符串中所有不重复的模式匹配项。 字符串从左到右扫描,并以找到的顺序返回匹配项。 如果该模式中存在一个或多个组,则返回一个组列表;否则,返回一个列表(list)。 如果模式包含多个组,则这将是一个元组列表(tuple)。 空匹配项包含在结果中。

例如:

message = 'verb very never every'
result = re.findall('.e',message)
print(result)
['ve', 've', 'ne', 've', ' e', 've']

re.sub(pattern,repl,string,counts,flags) [借助修改文本]

返回通过用repl替换字符串中最左边的非重叠模式所获得的字符串。 如果找不到该模式,则字符串将原样返回。 repl可以是字符串或函数; 如果是字符串,则处理其中的任何反斜杠转义。 也就是说,\ n转换为单个换行符,\ r转换为回车,依此类推。 ASCII字母的未知转义符保留供将来使用,并被视为错误。 其他未知的转义字符,例如\&,则任其保留。 反向引用(例如\ 6)将替换为模式中第6组匹配的子字符串。

例如:

content = 'WAN2356145507GYT'
content = re.sub('\d','O',content)
print(content)
WANOOOOOOOOOOGYT

re.compile(pattern,flags) [将正则表达式字符串编译成字符表达式对象,以便之后的匹配中复用]

将正则表达式模式编译为正则表达式对象,可使用在match()、search()和其他方法中将其用于匹配。

例如:

content1 = '2020/02/02 02:02'
content2 = '2020/02/20 02:20'
content3 = '2020/05/20 05:20'
pattern = re.compile('\d+:\d+')
result1 = re.sub(pattern,'',content1)
result2 = re.sub(pattern,'',content2)
result3 = re.sub(pattern,'',content3)
print(result1,result2,result3)
2020/02/02  2020/02/20  2020/05/20 

修饰符

flags[修饰符]
    1.re.I,使匹配对大小写不敏感
    2.re.L,做本地化识别匹配
    3.re.M,多行匹配,影响'^'和'?'
    4.re.S,使'.'匹配包括换行在内的所有字符

(来自集合“ a”,“ i”,“ L”,“ m”,“ s”,“ u”,“ x”的一个或多个字母。) 字母设置相应的修饰符:re.A(仅ASCII匹配),re.I(忽略大小写),re.L(取决于语言环境),re.M(多行),re.S(所有点均匹配) ,整个正则表达式的re.U(Unicode匹配)和re.X(详细)。 (修饰符在模块内容中描述。)如果希望将修饰符包括在正则表达式中,而不是将修饰符参数传递给re.compile()函数,则这很有用。 修饰符应首先在表达式字符串中使用。

实战使用

import requests,re,sys,time
from PyQt5.QtWidgets import (QWidget,QProgressBar,QPushButton,QApplication,QLabel)

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.epidemic()
        self.initUI()

    def initUI(self):
        self.pbar = []
        self.label = []
        for i in range(len(self.infos)):
            self.pbar.append(QProgressBar(self))
            self.pbar[i].setGeometry(200,80+40*i,200,25)
            self.pbar[i].setValue(0)
        for i in range(len(self.infos)):
            self.label.append(QLabel(self))
            self.label[i].setGeometry(50,80+40*i,200,25)
            self.label[i].setText('')


        self.btn = QPushButton('显示数据',self)
        self.btn.move(120,20)
        self.btn.clicked.connect(self.doAction)
        self.setGeometry(600,100,480,800)
        self.setWindowTitle('进度条')
        self.show()

    def epidemic(self):
        url = 'http://www.5ppt.net/aricle.asp?id=3947&p='
        self.infos = []
        for i in range(1,5):
            url_new = url + str(i)
            r = requests.get(url_new)
            if r.status_code == 200:
                r.encoding = r.apparent_encoding
                result = re.findall('([\u4e00-\u9fa5]+):(\d+)例',r.text)
                if result != []:
                    for one_info in result:
                        self.infos.append(one_info)
        print(self.infos)

    def doAction(self):
        self.btn.setText('整理中...')
        for i in range(len(self.infos)):
            time.sleep(0.3)
            self.pbar[i].setValue(int(self.infos[i][1])/1000)
            text = re.search('[\u4e00-\u9fa5]+',self.infos[i][0])
            self.label[i].setText(text[0])
        self.btn.setText('显示完成')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
TAG

网友评论

共有访客发表了评论
请登录后再发布评论,和谐社会,请文明发言,谢谢合作! 立即登录 注册会员