zoukankan      html  css  js  c++  java
  • Python 学习笔记之——正则表达式

    0. 常用匹配规则

    • ^ 匹配字符串的开头
    • $ 匹配字符串的结尾
    • [...] 匹配一组字符,比如 [abc] 表示匹配小写字母 a 或者 b 或者 c[a-z] 表示匹配所有的小写字母,[0-3] 表示匹配数字 0,1,2,3
    • [^...] 匹配不在 []中的字符
    • . 匹配除了换行符以外的任意字符,当匹配模式指定为 re.S 时则可以匹配任意字符
    • * 匹配零个或者多个表达式
    • + 匹配一个或者多个表达式
    • 匹配零个或者一个前面的表达式,非贪婪方式,也就是尽可能少地匹配
    • {n} 精确匹配 n 个前面的表达式,比如 s{2} 必须匹配字符串中连续的两个 s
    • {n,m} 匹配 n 到 m 个前面的表达式,贪婪方式,也即是尽可能多地匹配。比如 s{1,3} 可以匹配 1 到 3 个 s,但是如果有 3 个就全部匹配
    • {n,} 匹配至少 n 个前面的表达式,比如 s{1,} 等价于 s+s{0,} 等价于 s*
    • a|b 匹配 a 或者 b
    • d 匹配任意数字,也即 0-9
    • D 匹配任意非数字
    • w 匹配字母数字和下划线
    • W 匹配非字母数字和下划线
    • s 匹配任意空白字符,也即 Tab 、换行符 、回车符 和 换页符f
    • S 匹配任意非空白字符
    • A 匹配字符串开始
    •  匹配字符串结尾

    1. re.match

    函数原型:

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

    re.match 尝试从待匹配字符串的第一个字符开始匹配,如果匹配不成功就返回 None。

    • pattern 匹配的正则表达式
    • string 待匹配的字符串
    • flag=0 指定匹配模式,比如 re.I 使得匹配对大小写不敏感,re.S 使得 . 匹配符可以匹配包含换行符在内的所有字符
    content = 'I am seniusen!'
    res = re.match('I am.*', content)
    print(res.group()) # I am seniusen!
    res = re.match('Q am.*', content)
    print(res) # None
    

    指定匹配模式

    content = 'I AM SENIUSEN!'
    res = re.match('i am seniusen', content)
    print(res) # None
    res = re.match('i am seniusen!', content, re.I)
    print(res.group()) # I AM SENIUSEN!
    

    还可以用 | 将两个匹配模式组合起来一起使用

    content = '''I AM 
    SENIUSEN!'''
    res = re.match('i am.*', content, re.I)
    print(res.group()) # I AM
    res = re.match('i am.*', content, re.I|re.S)
    print(res.group())
    # I AM 
    # SENIUSEN!
    

    用括号可以获取匹配到的内容,res.group(1) 代表第一个括号内匹配的内容,res.group(2) 代表第二个括号内匹配的内容

    content = 'My name is seniusen, I was born in 1997, Henan, China.'
    res = re.match('My.*?(d+).*', content)
    print(res.group())
    # My name is seniusen, I was born in 1997, Henan, China.
    print(res.group(1)) # 1997
    res = re.match('My.*?(d{1,3}).*', content)
    print(res.group(1)) # 199
    

    上面 .* 可以匹配任意的非换行字符,? 代表非贪婪模式,也就是一旦遇到了数字,就交给括号里面的 d+ 来匹配,所以得到了 1997

    content = 'My name is seniusen, I was born in 1997, Henan, China.'
    res = re.match('My.*(d+).*', content)
    print(res.group(1)) # 7
    res = re.match('My.*(d{1,3}).*', content)
    print(res.group(1)) # 7
    

    而如果去掉了 ?,则代表是贪婪模式,那么 .* 会一直匹配到 199 才结束,只留给 d+ 匹配一个数字 7

    如果涉及到一些特殊字符,比如 *$,它们在正则表达式匹配中有一些特定含义,那么就不能直接来匹配了,需要使用转义字符

    content = 'The total cost is $5.00*'
    res = re.match('The total cost is $5.00*', content)
    print(res) # None,$ 被当作了字符串结尾,无法匹配
    res = re.match('The total cost is $5.00*', content)
    print(res.group()) # The total cost is $5.00*
    

    2. re.search

    函数原型:

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

    其参数和 re.match 一样,但 re.search 尝试搜索整个字符串,然后返回第一个成功的匹配。

    content = 'I am seniusen!'
    res = re.match('am.*', content)
    print(res) # None
    res = re.search('am.*', content)
    print(res.group(), res.span())
    # am seniusen! (2, 14)
    # res.span() 返回匹配的位置
    

    3. re.findall

    函数原型:

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

    re.findall 尝试从待匹配字符串找出所有的匹配项,然后返回一个字符串列表。

    content = 'I am seniusen, 3 years ago I was 20 years old!'
    res = re.findall('sen', content)
    print(res) # ['sen', 'sen']
    res = re.findall('d+', content)
    print(res) # ['3', '20']
    

    4. re.sub

    函数原型:

    re.sub(pattern, repl, string, count=0, flags=0)

    re.sub 尝试从待匹配字符串中找出所有的匹配并进行替换。

    • repl 替换的字符串,也可以是一个函数
    • count=0 替换的最大次数,默认为零表示替换所有的匹配
    content = 'I am seniusen, 3 years ago I was 20 years old!'
    res = re.sub('d+', 'xxx', content)
    print(res)
    # I am seniusen, xxx years ago I was xxx years old!
    res = re.sub('(d+)s(.*?)s', r'1x 2s', content)
    print(res)
    # I am seniusen, 3x years ago I was 20x years old!
    res = re.sub('(d+)s(.*?)s', r'1x 2s', content, 1)
    print(res)
    # I am seniusen, 3x years ago I was 20 years old!
    

    上面第一次是将字符串中所有的数字替换为 xxx,第二次是在数字后添加一个 x。其中 1 代表前面第一个括号中匹配的内容,而 2 代表前面第二个括号中匹配的内容,注意这里避免转义要添加上 r。第三次我们则设置只能替换一次。

    def num2word(matched):
        word = {'3': 'three', '20': 'twenty'}
        return word[matched.group('num')]
    
    content = 'I am seniusen, 3 years ago I was 20 years old!'
    res = re.sub('(?P<num>d+)', num2word, content)
    print(res)
    # I am seniusen, three years ago I was twenty years old!
    

    上面的 repl 参数是一个函数,表示将匹配到的数字转化为其对应的英文单词。其中 ?P<num> 表示给匹配到的内容进行一个分组,然后通过 matched.group('num') 就可以很方便地取出这个匹配结果。上面的代码和下面这段等价。

    def num2word(matched):
        word = {'3': 'three', '20': 'twenty'}
        return word[matched.group()]
    
    content = 'I am seniusen, 3 years ago I was 20 years old!'
    res = re.sub('d+', num2word, content)
    print(res)
    

    5. re.compile

    函数原型:

    re.compile(pattern[, flags])

    re.compile 用于构建一个正则表达式对象,便于重复使用。

    content = 'I am seniusen, 3 years ago I was 20 years old!'
    pattern = re.compile('d+')  # 匹配至少一个数字
    res = pattern.match(content)
    print(res)  # None 从头开始,无法匹配数字
    res = pattern.search(content)
    print(res.group())  # 3 匹配第一个数字
    res = pattern.findall(content)
    print(res)  # ['3', '20'] 匹配到所有的数字
    res = pattern.findall(content, 0, 16)
    print(res)  # ['3'] 限制在第 1 到第 16 个字符之间查找
    

    获取更多精彩,请关注「seniusen」!

  • 相关阅读:
    关于 CS1595 MS的知识库还是不全面,反正它给我的解决方法不能用,偶只有这样做了....
    被一贴,一个以前写的邮件发送的小类库。记住了,不是内裤
    [下载]活学活用DataGrid控件与ADO.NET
    不同浏览器透明度的写法
    通过文件读取oep值
    菜单
    CWnd::OnContextMenu函数(右键单击弹出快捷菜单)
    poj 3349(hash)
    poj 3009(dfs+回溯 模拟)
    poj 3026 (bfs+prim)
  • 原文地址:https://www.cnblogs.com/seniusen/p/13438331.html
Copyright © 2011-2022 走看看