Python 玩转数据 19 - 数据操作 正则表达式 Regular Expressions 搜索模式匹配

引言

本文主要介绍一下 Python 正则表达式,搜索模式匹配。更多 Python 进阶系列文章,请参考 Python 进阶学习 玩转数据系列

内容提要:

  1. re 模块方法汇总

  2. match() vs. search()

  3. 常用的正则表达式通配符

  4. 用 Raw Strings 原始字符串

  5. MatchObject

  6. findall()

  7. Matching Flags
    re.IGNORECASE
    re.ASCII
    re.DOTALL
    re.MULTILINE
    re.VERBOSE

  8. 字符串操作 re.sub re.split

  9. 用 re.compile 更方便

  10. 字符串方法 和 正则匹配

  11. 匹配 Email 的例子

  12. 正则表达式基本语法应用
    简单字符匹配
    一些特殊意义的字符
    [ ] 中括号 Square brackets
    重复通配符 Wildcards match repeated characters
    命名提取匹配部分 Naming extracted components

re 模块方法汇总

MethodDescription
match (pattern, string, flags)From the beginning, return MatchObject if a match exists, None otherwise
search (pattern, string, flags)Search the entire string for match, return MatchObject if exists, None otherwise
findall (pattern, string, flags)Return a list of matches of the pattern within string
finditer (pattern, string, flags)Iterator of matches of patterns in string
fullmatch (pattern, string, flags)Apply pattern to full string, MatchObject or None returned
split (pattern, string, maxsplit, flags)Break string up by regex pattern
sub (pattern, repl, string, count, flags)Find match, replace it with repl. Return new string

match() vs. search()

match() :
● 返回一个 MatchObject 如果 0 或 多个字符从字符串起始位置匹配到正则表达式模式
● 返回 None 如果字符串起始位置没有匹配到模式

search() 扫描正个字符串返回:
● 一个相应的 MatchObject
● None 没有找到匹配到的

举例:
在这里插入图片描述
在这里插入图片描述

Code:

import re

def match_search(regex, search_str):
    if re.match(regex, search_str):
        print('match: begins with {0}'.format(regex))
    else:
        print('match: {0} not found at beginning'.format(regex))

    if re.search(regex, search_str):
        print('search: contains {0}'.format(regex))
    else:
        print('search: {0} not found within'.format(regex))

lor = '''THE LORD OF THE RINGS

V*art One 

THE FELLOWSHIP 
OF THE RING 

J.R.R.ToIkien'''

match_search('THE', lor)
match_search('THE LORD', lor)
match_search('LORD', lor)
match_search('ToIkien', lor)

regex = re.compile('\s+')

for s in ["     ", "abc  ", "  abc"]:
    if regex.match(s):
        print(repr(s), "matches")
    else:
        print(repr(s), "does not match")

常用的正则表达式通配符

Meta CharacterDescription
^from the start
$to the end
\swhitespace
\Snon-whitespace
\ddigit
\Dnon-digit
\walpha-numeric character
\Wnon-alpha-numeric character
\bword boundary
\Bnon-word boundary
.none-line break charcter
*0 or more characters
+1 or more characters
?0 or 1 character
{n}exactly n characters
{n,m}from n to m characters
{,m}up to m characters
`(nm
[abcd]a or b or c or d
[f-m]one of characters from f through m
[^xyz]not x or y or z
[a-zA-Z]one of any letters

用 Raw Strings 原始字符串

\ 反斜杠 backslash ,在字符串中是转义符,而在正则表达式中一个特殊的字符。
● 为了避免混淆反斜杠和转义字符,我们用原始字符串 Raw String
● 用 r’….’ 表示原始字符串 ,\ 在原始字符串不再是一个特殊字符串字符。

举例:
字符串中 \b 是一个特殊的符号,\\ 是表示字符 \,强调用不是转义符。
在这里插入图片描述
在这里插入图片描述

MatchObject

match() 或 search() 会返回一个 MatchObject
MatchObject 方法:
● start(n) – 返回特定分组的起始索引
● end(n) – 返回特定分组的终止索引
● span(n) – 返回特定分组的起止索引元组 values (start, end)
● groups() – 返回包含所有子分组的元组
● group(n) – 返回特定子分组的元组, zero is the whole match

举例:
在这里插入图片描述

代码:

matchobj = re.search(r'(\w+) (\w+) (\w+) (\w+)',
"Hobbits are an unobtrusive but very ancient people")
print("groups():",matchobj.groups())

for i in range(len(matchobj.groups())+1):    
    print("group({0}): {1}".format(str(i), matchobj.group(i)))
    print("start({}): {}".format(str(i), matchobj.start(i)))
    print("end({}): {}".format(str(i), matchobj.end(i)))

findall()

findall() 返回一个 list,是括号所匹配到的结果(如 matches_2),多个括号就会返回多个括号分别匹配到的结果(如 matches_3),如果没有括号就返回就返回整条语句所匹配到的结果(如 matches_1)。

第 1 个 regex 中不带有括号, 其输出的内容就是整个表达式所匹配到的内容。
第 2 个 regex 中带有1个括号,其输出的内容就是括号匹配到的内容,而不是整个表达式所匹配到的结果。
第 3 个 regex 中是带有2个括号的,我们可以看到其输出是一个list 中包含 2 个 tuple
在这里插入图片描述
Code:

import re

string = "Hobbits are an unobtrusive but very ancient people"
matches_1 = re.findall(r'\w+', string)
matches_2 = re.findall(r'(\w+) (\w+) (\w+) (\w+)', string)
matches_3 = re.findall(r'((\w+) (\w+) (\w+) (\w+))', string)
print("{0}\ncontains {1} words: {2}".format(string, len(matches_1), matches_1))
print("{0}\ncontains {1} words: {2}".format(string, len(matches_2), matches_2))
print("{0}\ncontains {1} words: {2}".format(string, len(matches_3), matches_3))

Matching Flags

● re.IGNORECASE - 忽略大小写 匹配
● re.ASCII - 只匹配 ASCII,而不是 unicode
● re.VERBOSE - use verbose-style regular expressions
● re.DOTALL - dot(.) 匹配任意字符,包括换行符
● re.MULTILINE - 多行匹配每行的开头或结尾

re.IGNORECASE

re.IGNORECASE 或简写为 re.I ,忽略大小写匹配。
在这里插入图片描述

re.ASCII

re.ASCII 或简写为 re.A ,ASCII表示ASCII码的意思,让 w, W, b, B, d, D, s和 S只匹配ASCII,而不是Unicode
在这里插入图片描述

re.DOTALL

re.DOTALL 或简写为 re.S,DOT表示 .,ALL表示所有,连起来就是.匹配所有,包括换行符n。默认模式下. 是不能匹配行符 n 的。

在这里插入图片描述

re.MULTILINE

re.MULTILINE 或简写为 re.M,多行模式,当某字符串中有换行符 n,默认模式下是不支持换行符特性的,比如:行开头 和 行结尾,而多行模式下是支持匹配行开头的。

在这里插入图片描述

re.VERBOSE

通常正则表达式都是一行,不是很好理解。所以,可以使用详细模式,正则表达式中可以加注解。但是详细模式有区别普通模式:

空格被忽略:
● 空格,tabs 符,回车符都会被胡烈
● 如果需要忽略一个空格,需要用转义符。

注释被忽略:
● 详细模式中,一个注释就像 Python 代码中的注释一样,以 # 开头直到行结束。

在这里插入图片描述
代码:

import re
pattern = r'''
(\(?\d{3}\)?)? # optional area code, parentheses optional
[-\s.]?        # optional separator, dash, space, or period
\d{3}          # 3-digit prefix
[-\s.]         # separator: dash, space or period
\d{4}          # final 4-digits
'''
phones = [
    '123-456-7890',
    '123 456 7890',
    '(123) 456-7890',
    '123.456,7890',
    '123-4567',
    'abc-dfg-7789'
]

valid = [ph for ph in phones if re.match(pattern, ph, re.VERBOSE)]
print('VERBOSE: Valid phones: {0}'.format(valid))

字符串操作 re.sub re.split

有两种方法用来处理经过模式匹配后的字符串

  1. newstr = re.sub (pattern, replacement, sourcestring) 替换模式匹配到的字符
  2. re.split (pattern, sourcestring) 用模式匹配到的作为分隔符

举例:
在这里插入图片描述

用 re.compile 更方便

如果一个匹配模式需要反复使用,那么用 re.compile(pattern) 更方便

pattern_obj = re.compile(pattern, re.VERBOSE)

举例:
在这里插入图片描述
在这里插入图片描述

字符串方法 和 正则匹配

regex.search() 方法和 str.index()str.find() 方法是相同功能的。
在这里插入图片描述
regex.sub() 方法像 str.replace()
在这里插入图片描述

匹配 Email 的例子

‘\w+@\w+.[a-z]{3}’ \w 只能匹配到字符,数字的字符,邮件里的 . 字符没法匹配到
在这里插入图片描述
我们可以用 \S 匹配非空字符。
‘\w+\S\w+@\w+.[a-z]{3}’
在这里插入图片描述

正则表达式基本语法应用

简单字符匹配

在这里插入图片描述

import re

lor = open('../Python_data_wrangling/Python_data_wrangling_data_raw/data_raw/LordOfTheRings.txt',encoding='utf-8').read()

frodo = re.compile('Frodo')
frodos = frodo.findall(lor)

gandalf = re.compile('Gandalf')
gandalfs = gandalf.findall(lor)

sauron = re.compile('Sauron')
saurons = sauron.findall(lor)

gollum = re.compile('Gollum')
gollums = gollum.findall(lor)

print("Frodo is mentioned {} times\nGandalf is mentioned {} times\nSauron is mentioned: {} times\nGollum is mentioned {} times".
      format(len(frodos),len(gandalfs), len(saurons), len(gollums)))
print("So who is the Lord of the Rings?")

输出:

Frodo is mentioned 1100 times
Gandalf is mentioned 466 times
Sauron is mentioned: 60 times
Gollum is mentioned 72 times
So who is the Lord of the Rings?

一些特殊意义的字符

如: ^ $ * + ? { } [ ] \ | ( )
如果只是想匹配到上面的这些字符,不能直接直接用,需要加上转义符 \
在这里插入图片描述

[ ] 中括号 Square brackets

如果内置的字符不够充分,用户可以自定义。可以用破折号表示范围
“[a-m]” 匹配小写字符 a 到 m 之间的字符
在这里插入图片描述

重复通配符 Wildcards match repeated characters

如果想匹配 5 个字符,可以用 “\w\w\w\w\w” 或 “\w{3}”

CharacterDescriptionExample
?Match 0 or 1 repetitions of preceding“ab?” matches “a” or “ab”
*Match 0 or more repetitions of preceding“ab*” matches “a”, “ab”, “abb”, “abbb”…
+Match 1 or more repetitions of preceding“ab+” matches “ab”, “abb”, “abbb”… but not “a”
{n}Match n repetitions of preeeding“ab{2}” matches “abb”
{m,n}Match between m and n repetitions of preceding“ab{2,3}” matches “abb” or “abbb”

例如:
[\w.]+ 表示 \w 或 . 出现一次或多次,也就能匹配到任意长度字符数字或 .
在这里插入图片描述

命名提取匹配部分 Naming extracted components

(?P<name>) 来将匹配的值分组成一个字典
在这里插入图片描述
code:

import re
email4 = re.compile('(?P<user>[\w.]+)@(?P<domain>\w+)\.(?P<suffix>[a-z]{3})')
match = email4.match('peter.zhang@gmail.com')
match.groupdict()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值