美文网首页
3.3 引用分组

3.3 引用分组

作者: 马小跳_ | 来源:发表于2018-12-13 20:32 被阅读3次

    括号不仅仅能把有联系的元素归拢起来并分组,还有其他的作用——使用括号后,正则表达式会保存每个分组真正匹配的文本,等到匹配完成后,通过group(num)之类的方法“引用”分组在匹配时捕获的内容。其中num表示对应括号的编号,括号分组的编号是从左向右计数,从1开始。因为“捕获”了文本,所以这种功能叫做捕获分组(capturing group)。对应的,这种括号叫做捕获型括号

    例3-16 引用捕获分组

    print(re.search(r"(\d{4})-(\d{2})-(\d{2})", "2018-12-13").group(1))  # 2018
    print(re.search(r"(\d{4})-(\d{2})-(\d{2})", "2018-12-13").group(2))  # 12
    print(re.search(r"(\d{4})-(\d{2})-(\d{2})", "2018-12-13").group(3))  # 13
    

    分组的编号从1开始。不过也有编号为0的分组,它是默认存在的,对应整个表达式匹配的文本。在很多语言中,调用group方法,如果不给出参数num,默认就等于调用group(0)

    例3-17 编号为0的分组

    print(re.search(r"(\d{4})-(\d{2})-(\d{2})", "2018-12-13").group())  # 2018-12-13
    print(re.search(r"(\d{4})-(\d{2})-(\d{2})", "2018-12-13").group(0))  # 2018-12-13
    

    有些表达式可能包括嵌套嵌套的括号,但是这都不影响编号:无论括号如何嵌套,分组的编号都是根据开括号的出现顺序来技术的;开括号是从左向右数起的第几个,这个括号分组的编号就是多少。

    例3-18 嵌套括号的分组编号

    regex = re.compile(r'(((\d{4})-(\d{2}))-(\d{2}))')
    print(regex.search("2018-12-13").group(0))  # 2018-12-13
    print(regex.search("2018-12-13").group(1))  # 2018-12-13
    print(regex.search("2018-12-13").group(2))  # 2018-12
    print(regex.search("2018-12-13").group(3))  # 2018
    print(regex.search("2018-12-13").group(4))  # 12
    print(regex.search("2018-12-13").group(5))  # 13
    

    例3-19 利用分组提取超链接的详细信息(注意处理空白和单双引号)

    regex = re.compile(r'<a\s+href\s*=\s*[\'"]?([^\'"\s]+)[\'"]?>([^<]+)</a>')
    print(regex.findall('<a href="www.baidu.com">百度一下</a>'))  # [('www.baidu.com', '百度一下')]
    print(regex.findall("<a href = 'www.360.com'>360</a>"))  # [('www.360.com', '360')]
    print(regex.findall("<a href =https://souhu.com>搜狐</a>"))  # [('https://souhu.com', '搜狐')]
    

    引用分组捕获的文本,不仅用于数据提取,也可以用于替换。比如希望将yyyy-mm-dd格式的日期变为mm/dd/yyyy,就可以使用正则表达式进行替换。

    在python中进行正则表达式替换的方法是re.sub(pattern, replacement, string),其中pattern是用来匹配被替换文本的表达式,replacement是要替换成的文本,string是要进行替换操作的字符串(原始字符串)。

    例3-21 正则表达式替换

    print(re.sub(r'[a-z]', 'a', '1m1n1x'))  # 1a1a1a
    

    replacement中也可以引用分组,形式是\num,其中的num是对应分组的编号。不过,replacement并不是一个正则表达式,而是一个普通字符串。根据字符串中的转义规定,\t是制表符,\n是换行符,\1\2却不是字符串中的合法转义序列,所以也必须指定replacement为原生字符串。

    例3-22 在替换中使用分组

    regex = re.compile(r"(\d{4})-(\d{2})-(\d{2})")
    print(regex.sub(r"\2/\3/\1", "2018-12-13"))  # 12/13/2018
    print(regex.sub(r"\1年\2月\3日", "2018-12-13"))  # 2018年12月13日
    

    值得注意的是,如果想在replacement中引用整个表达式匹配的文本,不能使用\0,即便使用原生字符串也不行。因为在字符串中,\0开头的转义序列通常表示用八进制形式表示的字符,\0本身表示ascii字符编码为0的字符。如果一定要引用整个表达式匹配的文本,可以稍加变通,给整个表达式加上一对括号,之后用\1来引用。

    例3-23 在替换中,使用\1代替\0

    # ASCII编码为0的字符无法显示
    print(re.sub(r'(\d{4})-(\d{2})-(\d{2})', '\0', '2018-12-13'))  # ''
    print(re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\0', '2018-12-13'))  # ''
    
    # 变通一下
    print(re.sub(r'((\d{4})-(\d{2})-(\d{2}))', r'[ \1 ]', '2018-12-13'))  # [ 2018-12-13 ]
    

    相关文章

      网友评论

          本文标题:3.3 引用分组

          本文链接:https://www.haomeiwen.com/subject/svfihqtx.html