模块儿.re

原创
2016/02/26 12:56
阅读数 45

简单介绍:

此模块儿常用来使用形式化模式搜索和修改文本,默认使用Perl的正则表达式语法为基础并提供了一些特定的与PYTHON的改进


正则表达:

.    匹配任意除\n之外的字符,在DOTALL模式中也能匹配换行符

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = '5\n2\n1'
    # 非re.S模式,此时.匹配除换行符之外的字符
    match = re.match(r'5.2.1', sources_str)
    if match:
        print match.group()
    print '-------------------------------------'
    # 为re.S模式,此时.匹配含换行符之外的字符
    match = re.match(r'5.2.1', sources_str, re.S)
    if match:
        print match.group()

if __name__ == '__main__':
    main()

\  转义字符,使后一个字符改变原有的意思,如果字符串中有字符*需要匹配则需\*或是字符集[*]

[]  匹配字符集合,可通过-表示范围,^表示取反,[A-Za-z0-9]则只匹配a-zA-Z0-9这个集合中的单个字

\d 匹配数字[0-9]

\D 匹配非数字[^\d]

\s 匹配空白字符[ \t\r\n\f\v]

\w 匹配单词字符[A-Za-z0-9_]

\W 匹配非单词字符[^\w]

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = 'LiManMan * phone number is 18814818764?'
    match = re.match(r'[a-zA-Z]+\s\*\s\w+\s\w+\s\w+\s\d+\W', sources_str)
    if match:
        print match.group()

if __name__ == '__main__':
    main()

*  匹配一个字符0或多次

+ 匹配一个字符1次或是多次

? cha匹配一个字符0次或是1次

{m} 匹配一个字符m次

{m,n} 匹配一个字符最小m次,{m,}表示至少匹配m次,{,n}表示最多匹配n次

*? +? ?? {m,n}? 使* + ?? {m,n}变为非贪婪模式

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = 'LiManMan * phone number is 18814818764'
    # 贪婪模式
    match = re.match(r'[a-zA-Z]{1,}\s[*]\s\w+\s\w+\s\w+\s\d+', sources_str)
    if match:
        print match.group()
    # 非贪婪模式
    match = re.match(r'[a-zA-Z]{1,}\s[*]\s\w+\s\w+\s\w+\s\d+?', sources_str)
    if match:
        print match.group()

if __name__ == '__main__':
    main()

^ 匹配字符串开头,多行模式中匹配每一行的开头

$  匹配字符串末尾,多行模式中匹配每一行的末尾

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = '5\n2\n1'
    # ^匹配单行模式, $用法一样
    match = re.findall(r'^\d', sources_str)
    if match:
        print match
    # ^匹配多行模式, $用法一样
    match = re.finditer(r'^\d', sources_str, re.M)
    if match:
        # 遍历迭代对象
        for cur_match in match:
            print cur_match.group()

if __name__ == '__main__':
    main()

\A 必须出现在字符串的开头和^的区别在于多行模式下依然单行匹配

\Z  必须出现在字符串的结尾和$的区别在于多行模式下依然单行匹配

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = '5\n2\n1'
    # \A和\Z匹配时候其实忽略re.M多行特性,只会匹配整个sources_str
    match = re.findall(r'\A\d\Z', sources_str, re.M)
    if match:
        print match

    print '-----------------------------------------------------'
    # 单行匹配测试
    match = re.findall(r'\A5\n2\n1\Z', sources_str, re.M)
    if match:
        print match

if __name__ == '__main__':
    main()

\b  仅匹配单词的分割处,常见的分割如空格/标点/换行等

\B   [^\b]

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = 'i#love#you!'
    # \b其实匹配的是任意字符分割符
    match = re.search(r'\blove\b', sources_str)
    if match:
        print match.group()

if __name__ == '__main__':
    main()

|  代表左右表达式任意匹配一个,总是线尝试匹配左边的表达式,一旦匹配成功则跳过匹配右边的表达式,如果|没有在()中则范围是整个表达式(因为|在正则表达式中有特殊含义所以要包含|的字符串必须\转义先)

() 表示表达式分组,从表达式左边开始每遇到一个分组的左括号,编号+1,另外分组表达式可以作为一个总体可以后接数量词

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = 'python linux oracle mysql'
    # ()和|结合使用可以同时匹配多个元素
    match = re.findall(r'(python|linux|mysql)', sources_str)
    if match:
        print match

if __name__ == '__main__':
    main()

(?iLmsux)iLmsux的每个字符代表一个匹配模式,只能用在正则表达式的开头,可选多个,匹配模式后面再说

(?P<name>pattern) 分组,除了原有的编号外再指定一个额外的别名

\<number> 引用编号为<number>的分组匹配到的字符串

(?:pattern) (...)的不分组版本,用于使用|或是后接数量词

(?#pattern) #后的内容将作为注释被忽略

(?=pattern) 之后的字符串需要匹配表达式后才能成功匹配,不消耗字符串内容

(?!pattern) 之后的字符串需要不匹配表达式才能成功匹配,不消耗字符串内容

(?<=pattern) 之前的字符串需要匹配表达式后才能成功匹配,不消耗字符串内容

(?<!pattern) 之前的字符串需要不匹配表达式才能成功匹配,不消耗字符串内容

(?(id/name)yes-pattern|no-pattern) 如果编号为id/别名为name的组匹配到字符,则需要匹配yes-pattern,否则需要匹配no-pattern

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """

    sources_str = 'inet 172.24.10.1  netmask 255.255.255.0'
    # 只有match返回的对象才能分组
    match = re.match(r'''inet
                         \s+
                         (?P<ipaddr>[0-9.]+)
                         \s+
                         netmask
                         \s+
                         (?P<netmask>[0-9.]+)''', sources_str, re.X)
    if match:
        print match.groupdict()

if __name__ == '__main__':
    main()

常用方法:

re.compile(pattern, flags=0) -> pattern            

说明:将正则表达式字符串编译成pattern对象(生成缓存对象,避免缓存查找开销),第二个参数flags是匹配模式,取值可以使用按位“|”表示同时生效,re.compile(pattern, re.I|re.M)和re.compile((?im)pattern是等价的

re.I 忽略大小写

re.M 多行模式,改变^和$的行为

re.S 点任意匹配模式,改变.行为

re.L 使预定义\w\W\b\B\s\S取决于当前区域设定

re.U 使预定义\w\W\b\B\s\S取决于unicode定义的字符属性

re.X 详细模式,这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释

pattern 编译时用的正则表达式字符串

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

说明:将pattern编译后应用于字符串,只有当被搜索字符串的开头匹配模式的时候才能查到匹配对象,成功返回的matchobject包含很多匹配的信息,如果没有匹配成功则返回None

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """
    sources_str = 'i love you.'
    # 编译正则表达式
    pattern_obj = re.compile(r'''[a-z]\s # match i
                                 [a-z]+\s# match love
                                 [a-z]+. # match you.''', re.X)
    # 匹配正则表达式
    match = re.match(pattern_obj, sources_str)
    if match:
        print match.group()

if __name__ == '__main__':
    main()

re.search(pattern, string, flags=0) -> match

说明:将pattern编译后应用于字符串,只要找到任意位置匹配子串则停止继续查找,成功返回的matchobject包含很多匹配的信息,如果没有匹配成功则返回None

re.split(pattern, string, maxsplit=0) -> list 

说明:按照能够匹配的子串将string切割后返回列表,maxsplit用于指定最大分割次数,不指定将全部分割

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re


def main():
    """Main function. """
    sources_str = 'i love you'
    # re.split可以用任意正则表达式分割字符串,以及设置分割的次数
    match = re.split(r'\s', sources_str, maxsplit=2)
    if match:
        print match

if __name__ == '__main__':
    main()

re.findall(pattern, string, flags=0) -> list

说明:搜索string字符串,将以列表形式返回全部能匹配的子串

re.finditer(pattern, string, flags=0) -> iterator

说明:搜索string字符串,返回一个顺序访问每一个匹配结果(Matach)对象的迭代器

re.sub(pattern, repl, string, count=0) -> str

说明:使用repl替换string中的每一个匹配的子串后返回替换后的字符串,当repl是一个字符串时,可以使用\g<id>或\g<name>引起分组,但不能使用编号0,当repl是一个方法时,这个方法应当只接受一个参数(match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组),count用于指定最多被替换多少次,不指定时全部替换

# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import re
import colorama


def highlight(match):
    """High light search_strs.

    Args:
        match: re match object
    Returns:
        string
    """

    colorama.init()
    return ''.join([colorama.Fore.RED, match.group(), colorama.Fore.RESET])


def main():
    """Main function."""
    # 定义搜索的文件
    user_file = '/etc/passwd'
    # 此时文件偏移为0
    with open(user_file, 'r+b') as rhandler:
        while True:
            search_strs = raw_input('please input search string: ').strip()
            if len(search_strs) == 0:
                continue
            if search_strs in ('quit', 'exit'):
                break
            for cur_line in rhandler:
                # 存在search_strs就高亮替换
                if search_strs in cur_line:
                    cur_line = re.sub(search_strs, highlight, cur_line)
                print cur_line,
            # 回到文件开头
            rhandler.seek(0)


if __name__ == '__main__':
    main()


pattern对象:

P.groups 表达式中分组的数量

P.groupindex 返回{分组键名,分组id}的字典,没有别名的分组不包含在内


match对象:

M.string 匹配时使用的文本

M.re 匹配时使用的pattern对象

M.pos 文本中正则表达式开始搜索的索引(默认是0)

M.endpos 文本中正则表达式结束搜索的索引(默认是文本的长度)

M.lastindex 最后一个被捕捉的分组在文本中的索引,如果没有被捕捉的分组则返回None

M.lastgroup 最后一个被捕捉的分组的别名,如果这个分组没有别名或者没有被捕获的分组则返回None

M.group([group1,...]) 获得一个或是多个分组字符串,参数可以有多个,group1可以是分组的别名或是id,默认参数不写或是group(0)则返回整个字符串,没有截获字符串的组返回None,截获了多次的组返回最后一次截获的子串

M.groups([default]) 以元组形式返回全部分组捕获的字符串,相当于调用group(1,2...last),default表示没有截获字符串的组时候返回此字符串,默认为None 

M.groupdict([default]) 返回以别名的组的别名为键,以该组截获的字串为值的字典,没有别名的组不包含在内,default表示没有截获字符串的组时候返回此字符串,默认为None

M.start([group]) 返回指定的组截获的字串在string的起始索引(子串的第一个字符的索引),group默认的值为0

M.end([group]) 返回指定的组截取的子串在string中的结束索引(子串最后一个字符的索引+1),group默认为0

M.span([group]) 返回一个元组,(start(group), end(group))

M.expand(string_template) 将匹配到的分组代入Template模版中返回,Template中可以使用\g<id>,\g<name>引用分组


展开阅读全文
打赏
1
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部