Python中正则表达式的深度解析

# coding: utf-8

import re 

常用函数

代码 3-1 使用 match 函数匹配文本

match 函数,从字符串‌起始位置‌匹配正则表达式,返回 Match 对象(匹配失败返回 None)。

text1 = '自然语言处理是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门融语言学、计算机科学、数学于一体的科学。'
print('匹配的结果是:', re.match(r'自然语言处理', text1))
print('匹配的结果是:', re.match(r'语言处理', text1))
匹配的结果是: <re.Match object; span=(0, 6), match='自然语言处理'>
匹配的结果是: None
pattern = r'hello'
string = 'hello world'
result = re.match(pattern, string, flags=re.I)  # flags=re.I 忽略大小写 ‌:ml-citation{ref="3,5" data="citationList"}
if result:
    print(result.group())  # 输出: hello    
hello

代码 3-2 split 函数 按正则表达式分割字符串,返回列表。

# 以句号为分隔符通过split切分text1
p_string = text1.split(r'。')  
print(p_string)
# 按行读取 p_string
for line in p_string:
    # print(line)
    # 查找当前行是否匹配 “自然语言处理”
    if re.match(r'自然语言处理', line) is not None:
        # 如果匹配到,那么打印这行信息
        print(line)        
['自然语言处理是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法', '自然语言处理是一门融语言学、计算机科学、数学于一体的科学', '']
自然语言处理是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法
自然语言处理是一门融语言学、计算机科学、数学于一体的科学

代码 3-3 search 函数,在字符串中‌搜索第一个匹配项‌,返回 Match 对象。

# 返回一个匹配
print(re.search('通信', text1) ) 
<re.Match object; span=(28, 30), match='通信'>

代码 3-4

findall 函数,返回所有匹配的子字符串‌列表‌。

finditer 函数,返回所有匹配项的‌迭代器‌(每个元素为 Match 对象)。

# 返回一个匹配项列表
print(re.findall(r'计算机', text1)) 

# 返回一个匹配项的‌迭代
for match in re.finditer(r'计算机', text1):
    print(match.group(), end=' ')
['计算机', '计算机']
计算机 计算机 

3-5 sub 函数,替换字符串中所有匹配项,返回新字符串。

print(re.sub(r'自然语言处理', r'NLP', text1))
NLP是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。NLP是一门融语言学、计算机科学、数学于一体的科学。

常用正则标志(flags)‌

  • re.I:忽略大小写。
  • re.M:多行模式(使 ^ 和 $ 匹配每行开头和结尾)。
  • re.S:使 . 匹配包括换行符在内的所有字符。
  • 附:‌贪婪匹配与最小匹配‌

  • 贪婪匹配‌:.* 默认匹配尽可能长的字符串。
  • 最小匹配‌:使用 .*? 匹配尽可能短的字符串。
  • 元字符

    元字符分类速查(结合案例说明)

    1. 基础匹配

      r'.' 匹配除换行外任意字符(例:a.c 匹配 abc)

      r'\d' 数字 [0-9](例:\d{3} 匹配 123)

      r'\D' 非数字 [^0-9]

      r'\s' 空白字符(例:匹配空格、制表符)

    2. 定位符

      r'^' 字符串开始(例:^Hello 匹配行首Hello)

      r'$' 字符串结束(例:end$ 匹配行末end)

      r'\b' 单词边界(例:\bcat\b 匹配独立单词cat)

    3. 量词

      r'*' 0次或多次(例:a* 匹配 aa)

      r'+' 1次或多次(例:\d+ 匹配连续数字)

      r'?' 0次或1次(例:colou?r 匹配 color/colour)

      r'{n,m}' 次数范围(例:a{2,4} 匹配 aa到aaaa)

    4. 特殊符号

      r'[]' 字符集合(例:[A-Za-z] 所有字母)

      r'|' 或操作(例:cat|dog 匹配cat或dog)

      r'()' 捕获分组(例:(ab)+ 匹配abab)

    代码 3-6

    r’.’ 因为字符 . 匹配除换行外任意字符(例:a.c 匹配 abc) 一个 . 只能匹配一个字符

    # 匹配未知字符“然”
    print(re.findall(r'自.语言处理', text1) ) 
    
    ['自然语言处理', '自然语言处理']
    

    代码 3-7 字符集合

    匹配 [] 内任意一个字符

    # 匹配[]内的任意一个字符
    print(re.findall(r'[科数]学', text1))  
    
    ['科学', '数学', '科学']
    

    代码 3-8 或操作 | 多关键词过滤

    print(re.findall(r'方法|计算机', text1))
    
    ['计算机', '方法', '计算机']
    

    代码 3-9 输出含有方法或者计算机的句子

    # 以句号为分隔符通过split切分text1
    p_string = text1.split(r'。')  
    # 按行读取 p_string
    for line in p_string:
        # 查找当前行是否匹配 “自然语言处理”
        if re.findall(r'方法|计算机', line) is not None:
            # 如果匹配到,那么打印这行信息
            print(line)        
    
    自然语言处理是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法
    自然语言处理是一门融语言学、计算机科学、数学于一体的科学
    

    代码 3-10 匹配以 开头的字符串

    r’^’ 字符串开始(例:^Hello 匹配行首Hello)

    # 以句号为分隔符通过split切分text1
    p_string = text1.split(r'。')  
    # 按行读取 p_string
    for line in p_string:
        # 查找当前行是否^匹配 “自然语言处理”
        if re.findall(r'^自', line) is not None:
            # 如果匹配到,那么打印这行信息
            print(line)      
    
    自然语言处理是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法
    自然语言处理是一门融语言学、计算机科学、数学于一体的科学
    

    代码 3-11 匹配以 结尾的字符串

    $ 结尾匹配(文件扩展名检测)

    p_string = text1.split('、')
    for line in p_string:  
        if len(re.findall(r'学$', line)):
            print(line)
    
    自然语言处理是研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门融语言学
    计算机科学
    

    代码 3-12 量化符 ? * + {n} {n,} {n,m}

    量化符 说明
    ? 前面的元素可选
    * 前面的元素被匹配 0 次或多次
    + 前面的元素被匹配 1 次或多次
    {n} 前面的元素被匹配 n
    {n,} 前面的元素至少被匹配 n
    {n,m} 前面的元素至少被匹配 n 次,至多匹配 m

    代码 3-13 转移字符 \

    # 唐初著名诗人刘希夷的诗《代悲白头吟》其中两句
    text2 = '今年花落颜色改,明年花开复谁在?年年岁岁花相似,岁岁年年人不同。'
    
     # “年”最多重复1次
    print(re.findall(r'年?', text2)) 
    
    # “年”可以重复0或多次
    print(re.findall(r'年*', text2))  
    
    # “年”可以重复1次或多次
    print(re.findall(r'年+', text2))
    
    # “年”正好被重复1次
    print(re.findall('r年{1}', text2) ) 
    
    # “年”正好被重复2次
    print(re.findall(r'年{2}', text2))
    
    # “年”至少重复0次,至多重复1次
    print(re.findall(r'年{0,1}', text2))
    
    # 以年开始,后面可以跟任意多个字符
    print(re.findall(r'年.+', text2) ) 
    
    # “年”可以重复1次或多次,后面跟任意字符
    print(re.findall(r'年+.', text2))  
    
    # “年”后面至多可以跟1个任意字符
    print(re.findall(r'年.?', text2)) 
    
    # “年”后面可以跟任意多个字符
    print(re.findall(r'年.*', text2) ) 
    
    # “年”后面可以跟一个任意字符,并且这两个字符最多重复1次
    print(re.findall(r'年.+?', text2))  
    
    # “年”后面允许不带其他字符的内容。
    print(re.findall(r'年.*?', text2))  
    
    #“花”前面的“年”最多重复1次
    print(re.findall(r'年?花', text2))  
    
    # “花”前面的“年”可以重复0或多次
    print(re.findall(r'年*花', text2))  
    
     # “花”前面的“年”可以重复1次或多次
    print(re.findall('年+花', text2)) 
    
    # “花”前面的“年”重复1次
    print(re.findall(r'年{1}花', text2)) 
    
    # “花”前面的“年”重复2次
    print(re.findall('年{2}花', text2)) 
    
    # “花”前面的“年”至少重复0次,至多重复1次
    print(re.findall(r'年{0,1}花', text2))
    
    # “年”开头“花”结尾且中间的任意字符可以任意多个
    print(re.findall(r'年.+花', text2) ) 
    
    # “年”开头“花”结尾且中间的任意字符至多一个
    print(re.findall(r'年.?花', text2))  
    
    # “年”开头“花”结尾且中间的任意字符可以任意多个
    print(re.findall(r'年.*花', text2) )
    
    # “年”开头“花”结尾且中间至少带有一个字符的内容
    print(re.findall(r'年.+?花', text2))  
    
    # “年”开头“花”结尾中间允许不带其他字符的内容
    print(re.findall(r'年.*?花', text2))
    
    ['', '年', '', '', '', '', '', '', '', '年', '', '', '', '', '', '', '年', '年', '', '', '', '', '', '', '', '', '年', '年', '', '', '', '', '']
    ['', '年', '', '', '', '', '', '', '', '年', '', '', '', '', '', '', '年年', '', '', '', '', '', '', '', '', '年年', '', '', '', '', '']
    ['年', '年', '年年', '年年']
    []
    ['年年', '年年']
    ['', '年', '', '', '', '', '', '', '', '年', '', '', '', '', '', '', '年', '年', '', '', '', '', '', '', '', '', '年', '年', '', '', '', '', '']
    ['年花落颜色改,明年花开复谁在?年年岁岁花相似,岁岁年年人不同。']
    ['年花', '年花', '年年岁', '年年人']
    ['年花', '年花', '年年', '年年']
    ['年花落颜色改,明年花开复谁在?年年岁岁花相似,岁岁年年人不同。']
    ['年花', '年花', '年年', '年年']
    ['年', '年', '年', '年', '年', '年']
    ['年花', '年花', '花']
    ['年花', '年花', '花']
    ['年花', '年花']
    ['年花', '年花']
    []
    ['年花', '年花', '花']
    ['年花落颜色改,明年花开复谁在?年年岁岁花']
    ['年花', '年花']
    ['年花落颜色改,明年花开复谁在?年年岁岁花']
    ['年花落颜色改,明年花', '年年岁岁花']
    ['年花', '年花', '年年岁岁花']
    
    ## 正则表达式应用
    

    代码 3-14 网页查看西游记文本内容

    text3 = 'Hello,everyone,想做/ 兼_职/ 的 亲_/  、加,我.微。信。wxid_6cp3ve3hdfut11,1.3。1、4     有,惊,喜,哦'
    
    # 将text3中的阿拉伯数字替换为“数字”
    print(re.sub('\\d', '数字', text3))  
    
    # 将数字替换为“数字”
    print(re.sub(r'\d', '数字', text3)) 
    
    # # 将数字替换为“数字”
    print(re.sub(r'[0-9]', '数字', text3))
    
    # 删除空白
    print(re.sub(r'\s', '', text3))
    
    # 删除字和数字
    print(re.sub(r'\w', '', text3))
    
    # 查找带有多个英文字母的字符
    print(re.findall('\\b[a-zA-Z]+', text3))
    
    # 查找只带有字母的单词
    print(re.findall('\\b[a-zA-Z]+\\b', text3))
    
    Hello,everyone,想做/ 兼_职/ 的 亲_/  、加,我.微。信。wxid_数字cp数字ve数字hdfut数字数字,数字.数字。数字、数字     有,惊,喜,哦
    Hello,everyone,想做/ 兼_职/ 的 亲_/  、加,我.微。信。wxid_数字cp数字ve数字hdfut数字数字,数字.数字。数字、数字     有,惊,喜,哦
    Hello,everyone,想做/ 兼_职/ 的 亲_/  、加,我.微。信。wxid_数字cp数字ve数字hdfut数字数字,数字.数字。数字、数字     有,惊,喜,哦
    Hello,everyone,想做/兼_职/的亲_/、加,我.微。信。wxid_6cp3ve3hdfut11,1.3。1、4有,惊,喜,哦
    ,,/ /  /  、,.。。,.。、     ,,,
    ['Hello', 'everyone', 'wxid']
    ['Hello', 'everyone']
    
    from urllib.request import urlopen
    
    url1 = 'http://www.gutenberg.org/cache/epub/23962/pg23962.html'  # 西游记文本网址
    html1 = urlopen(url1).read()
    html1 = html1.decode('utf-8')
    # print(html1)
    text4 = html1[2269:2450]  # 查看部分内容
    print(text4)
    
       }
    /* ************************************************************************
     * set the indention, spacing, and leading for body paragraphs.
     * ******************************
    

    代码 3-15

    # 过滤掉所有英文字符、数字及英文特殊符号
    print(re.sub(r'[\[\]\s+\.\!\/_,$%^*(+\"\'?:&@#;<>=-]+|[a-zA-Z]+|[0-9]+', r'', text4))
    # 除标点符号外,过滤掉所有英文字符、数字及中英文特殊符号
    print(re.sub(r'[\[\]\s+\.\!\/_,$%^*(+\"\'?:&@#;<>=-]+|[+——!?~@#¥%……&*()」「]+|[a-zA-Z]+|[0-9]+',r'', text4))
    # 过滤掉所有标点符号、英文字符、数字及中英文特殊符号
    print(re.sub(r'[\[\]\s+\.\!\/_,$%^*(+\"\'?:&@#;<>=-]+|[+——!?~@#¥%……&*()」「]+|[《》 ,。;﹔、:-]+|[a-zA-Z]+|[0-9]+', r'', text4))
    
    }
    }
    }
    

    代码 3-16

    text5 = 'J. Done: 234-555-1234J. Smith: (888) 555-1234A. Lee: (810)555-1234M. Jones: 666.555.9999'
    name = re.findall(r'[A-Z][\.a-zA-Z]+', text5)
    for i in name:
        print(i)  # 打印人名
    
    J.
    Done
    J.
    Smith
    A.
    Lee
    M.
    Jones
    

    代码 3-17

    tel = re.findall('[0-9(][0-9- ).]+', text5)
    for i in tel:
        print(i)  # 打印电话号码
    
    234-555-1234
    (888) 555-1234
    (810)555-1234
    666.555.9999
    

    代码 3-18

    for i in zip(name, tel):  # zip是将元素打包成元组
        print(i)  # 打印人名及电话号码
    
    ('J.', '234-555-1234')
    ('Done', '(888) 555-1234')
    ('J.', '(810)555-1234')
    ('Smith', '666.555.9999')
    

    代码 3-19

    text6 = '<a href="http://www.baidu.com">百度</a> <a href="http://www.google.com">谷歌</a>'
    # 第一个“.*?”表示从a开始匹配到出现双引号之间的字符,第二个“.*?”则是提取的内容
    url = re.findall('<a.*?"(.*?)">', text6)
    # 第一个“.*?”表示从a开始匹配到出现“>”之间的字符,第二个“.*?”则是提取的内容
    name = re.findall('<a.*?>(.*?)<', text6)
    for i in range(len(name)):
        print(name[i] + '。' + url[i])
    
    百度。http://www.baidu.com
    谷歌。http://www.google.com
    

    作者:李昊哲小课

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中正则表达式的深度解析

    发表回复