zoukankan      html  css  js  c++  java
  • Python正则表达式

    简单介绍

    知道[正则表达式]可能意味着用 3 步解决一个问题,而不是用 3000 步。如果你是一个技术怪侠,别忘了你用几次击键就能解决的问题,其他人需要数天的烦琐工作才能解决,而且他们容易犯错。

    正则表达式英文名(regex)

    由一个例子开始讲解基本方法

    例子

    >>> import re
    >>> phoneNumRegex = re.compile(r'ddd-ddd-dddd')
    >>> mo = phoneNumRegex.search('My number is 415-555-4242.')
    >>> print('Phone number found: ' + mo.group())
    Phone number found: 415-555-4242
    

    解释:

    虽然在 Python 中使用正则表达式有几个步骤,但每一步都相当简单。
    1.用 import re 导入正则表达式模块。
    2.用 re.compile()函数创建一个 Regex 对象(记得使用原始字符串)。
    3.向 Regex 对象的 search()方法传入想查找的字符串。它返回一个 Match 对象。
    4.调用 Match 对象的 group()方法,返回实际匹配文本的字符串。

    search和findall()比较

    除了search()外,还有一个findall()。
    search()将返回一个Match对象,包含被查找字符串中的“第一次”匹配的文本,而 findall()方法将返回一组字符串,包含被查找字符串中的所有匹配。
    比较
    search()

    >>> phoneNumRegex = re.compile(r'ddd-ddd-dddd')
    >>> mo = phoneNumRegex.search('Cell: 415-555-9999 Work: 212-555-0000')
    >>> mo.group()
    '415-555-9999'
    

    findall()

    >>> phoneNumRegex = re.compile(r'ddd-ddd-dddd') # has no groups
    >>> phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
    ['415-555-9999', '212-555-0000']
    

    作为 findall()方法的返回结果的总结,请记住下面两点:
    1.如果调用在一个没有分组的正则表达式上,例如ddd-ddd-dddd,方法
    findall()将返回一个匹配字符串的列表,例如['415-555-9999', '212-555-0000']。

    >>> phoneNumRegex = re.compile(r'ddd-ddd-dddd') # has no groups
    >>> phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
    ['415-555-9999', '212-555-0000']
    

    2.如果调用在一个有分组的正则表达式上,例如(ddd)-(ddd)-(dddd),方
    法 findall()将返回一个字符串的元组的列表(每个分组对应一个字符串),例如[('415',
    '555', '1122'), ('212', '555', '0000')]

    >>> phoneNumRegex = re.compile(r'(ddd)-(ddd)-(dddd)') # has groups
    >>> phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
    [('415', '555', '1122'), ('212', '555', '0000')]
    

    sub()方法替换字符串

    第一个参数用于取代发现的文本,第二个参数是那条长长的字符串

    >>> namesRegex = re.compile(r'Agent w+')
    >>> namesRegex.sub('CENSORED', 'Agent Alice gave the secret documents to Agent Bob.')
    'CENSORED gave the secret documents to CENSORED.'
    

    方法总结:

    compile() 创建一个用正则表达式的对象
    search() 找到第一个匹配的
    findall() 找到所有匹配的
    group() 显示出匹配的
    sub() 替换字符串

    利用括号分组

    (ddd)-(ddd-dddd),让gruop中有更多的花样

    >>> mo.group(1)
    '415'
    >>> mo.group(2)
    '555-4242'
    >>> mo.group(0)
    '415-555-4242'
    >>> mo.group()
    '415-555-4242'
    

    符号 ?* + {}

    ?匹配这个问号之前的分组零次或一次

    >>> batRegex = re.compile(r'Bat(wo)?man')
    >>> mo1 = batRegex.search('The Adventures of Batman')
    >>> mo1.group()
    'Batman'
    >>> mo2 = batRegex.search('The Adventures of Batwoman')
    >>> mo2.group()
    'Batwoman'
    

    *星号匹配零次或多次

    >>> batRegex = re.compile(r'Bat(wo)*man')
    >>> mo1 = batRegex.search('The Adventures of Batman')
    >>> mo1.group()
    'Batman'
    >>> mo2 = batRegex.search('The Adventures of Batwoman')
    >>> mo2.group()
    'Batwoman'
    >>> mo3 = batRegex.search('The Adventures of Batwowowowoman')
    >>> mo3.group()
    'Batwowowowoman'
    

    +加号匹配一次或多次

    >>> batRegex = re.compile(r'Bat(wo)+man')
    >>> mo1 = batRegex.search('The Adventures of Batwoman')
    >>> mo1.group()
    'Batwoman'
    >>> mo2 = batRegex.search('The Adventures of Batwowowowoman')
    >>> mo2.group()
    'Batwowowowoman'
    >>> mo3 = batRegex.search('The Adventures of Batman')
    >>> mo3 == None
    True
    

    {}花括号匹配特定次数
    {n}匹配 n 次前面的分组。
    {n,}匹配 n 次或更多前面的分组。
    {,m}匹配零次到 m 次前面的分组。
    {n,m}匹配至少 n 次、至多 m 次前面的分组。
    {n,m}?或*?或+?对前面的分组进行非贪心匹配。

    >>> haRegex = re.compile(r'(Ha){3}')
    >>> mo1 = haRegex.search('HaHaHa')
    >>> mo1.group()
    'HaHaHa'
    >>> mo2 = haRegex.search('Ha')
    >>> mo2 == None
    True
    

    符号总结

     ?匹配零次或一次前面的分组。
    匹配零次或多次前面的分组。
     +匹配一次或多次前面的分组。
     {n}匹配 n 次前面的分组。
     {n,}匹配 n 次或更多前面的分组。
     {,m}匹配零次到 m 次前面的分组。
     {n,m}匹配至少 n 次、至多 m 次前面的分组。
     {n,m}?或
    ?或+?对前面的分组进行非贪心匹配。

    字符分类

    d,w,s,数字,字母,符号

    d 0 到 9 的任何数字
    D 除 0 到 9 的数字以外的任何字符
    w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
    W 除字母、数字和下划线以外的任何字符
    s 空格、制表符或换行符(可以认为是匹配“空白”字符)
    S 除空格、制表符和换行符以外的任何字符

    建立自己的字符分类

    >>> vowelRegex = re.compile(r'[aeiouAEIOU]')
    >>> vowelRegex.findall('RoboCop eats baby food. BABY FOOD.')
    ['o', 'o', 'o', 'e', 'a', 'a', 'o', 'o', 'A', 'O', 'O']
    

    字符分类[a-zA-Z0-9]将匹配所有小写字母、大写字母和数字。
    []中一般的不怎么需要 倒斜杠转义.、*、?或()字符
    [^a]非a字符

    通配字符 .

    >>> atRegex = re.compile(r'.at')
    >>> atRegex.findall('The cat in the hat sat on the flat mat.')
    ['cat', 'hat', 'sat', 'lat', 'mat']
    

    点-星将匹配除换行外的所有字符。
    通过传入 re.DOTALL 作为 re.compile()的第二个参数,可以让句点字符匹配所有字符,包括换行字符。

    >>> newlineRegex = re.compile('.*', re.DOTALL)
    >>> newlineRegex.search('Serve the public trust.
    Protect the innocent.
    Uphold the law.').group()
    'Serve the public trust.
    Protect the innocent.
    Uphold the law.'
    

    匹配时不区分大小写,可以向 re.compile()传入 re.IGNORECASE 或 re.I,作为第二个参数。

    管理复杂的正则表达式

    不是所有的正则表达式都很短的,向re.compile()中写入re.VERBOSE,可以忽略正则表达式字符串中的空白符和注释
    原来

    phoneRegex = re.compile(r'((d{3}|(d{3}))?(s|-|.)?d{3}(s|-|.)d{4}(s*(ext|x|ext.)s*d{2,5})?)')
    

    加入后

    phoneRegex = re.compile(r'''(
        (d{3}|(d{3}))? # area code
        (s|-|.)? # separator
        d{3} # first 3 digits
        (s|-|.) # separator
        d{4} # last 4 digits
        (s*(ext|x|ext.)s*d{2,5})? # extension
        )''', re.VERBOSE)
    

    compile的第二个参数总结

    re.IGNORECASE 忽略大小写
    re.VERBOSE 来编写注释
    re.DOTALL 句点字符匹配换行

    用管道符号可以一起传入,例如,既忽略大小写又句点字符匹配换行

    >>> someRegexValue = re.compile('foo', re.IGNORECASE | re.DOTALL)
    

    参考书籍

    《Python编程快速上手》

  • 相关阅读:
    向eureka注册正确的ip地址
    sleuth + zipkin 链路分析
    Yii2的整体结构概览
    Redis实现消息队列
    Redis使用场景梳理
    redis基础知识
    TCP服务
    数据结构-队列
    看见
    线性表的链式存储结构
  • 原文地址:https://www.cnblogs.com/wudongwei/p/8988166.html
Copyright © 2011-2022 走看看