Author: Seven_0507
Date: 2019-05-24
本次主要总结字符串的高级用法及正则表达式的使用及练习!
正则表达式中的一些基本符号如下:
参考《正则表达式30分钟入门教程》
常用的元字符 | |||
---|---|---|---|
符号 | 解释 | 示例 | 说明 |
. | 匹配除换行符以外的任意字符 | b.t | 可以匹配bat / but / b#t / b1t等 |
\w | 匹配字母/数字/下划线/汉字 | b\wt | 可以匹配bat / b1t / b_t等,但不能匹配b#t |
\s | 匹配空白字符(包括\r、\n、\t等),中文全角空格等 | love\syou | 可以匹配love you |
\d | 匹配数字 | \d\d | 可以匹配01 / 23 / 99等 |
\b | 匹配单词的边界(匹配单词的开始或结束) | \bThe\b | |
^ | 匹配字符串的开始 | ^The | 可以匹配The开头的字符串 |
$ | 匹配字符串的结束 | .exe$ | 可以匹配.exe结尾的字符串 |
常用的反义代码 | |||
\W | 匹配非字母/数字/下划线/汉字的字符 | b\Wt | 可以匹配b#t / b@t等,但不能匹配but / b1t / b_t等 |
\S | 匹配非空白字符(包括\r、\n、\t等),中文全角空格等 | love\Syou | 可以匹配love#you等,但不能匹配love you |
\D | 匹配非数字 | \d\D | 可以匹配9a / 3# / 0F等 |
\B | 匹配非单词边界 | \Bio\B | |
[^x] | 匹配除了x以外的任意字符 | ||
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 | ||
字符类 | |||
[ ] | 匹配来自字符集的任意单一字符(匹配没有预定义元字符的字符集合) | [aeiou] | 可以匹配任一元音字母字符 |
[^] | 匹配不在字符集中的任意单一字符 | [^aeiou] | 可以匹配任一非元音字母字符 |
常用的限定符 | |||
* | 匹配0次或多次 | \w* | |
+ | 匹配1次或多次 | \w+ | |
? | 匹配0次或1次 | \w? | |
{N} | 匹配N次 | \w{3} | |
{M,} | 匹配至少M次 | \w{3,} | |
{M,N} | 匹配至少M次至多N次 | \w{3,6} | |
分支条件 | |||
| | 分支,有几种规则若满足任意一种规则都应当成匹配,左到右地测试每个条件匹配到第一个满足的分支结束 | foo|bar | 可以匹配foo或者bar |
常用分组语法 | |||
(exp) | 匹配exp并捕获到自动命名的组中,用小括号来指定子表达式,就可指定重复次数或其它一些操作 | (\d{1,3}.){3} | 匹配1到3位的数字加.,重复3次,(eg:IP地址匹配规则) |
(? exp) | 匹配exp并捕获文本到名称为name的组里,也可以写成(?'name’exp) | (?\w+) | \w+的组名指定为Word |
(?:exp) | 匹配exp但是不捕获匹配的文本,也不给此分组分配组号 | ||
(?=exp) | 匹配exp前面的位置 | \b\w+(?=ing) | 可以匹配I’m dancing中的danc |
(?<=exp) | 匹配exp后面的位置 | (?<=\bdanc)\w+\b | 可以匹配I love dancing and reading中的第一个ing |
(?!exp) | 匹配后面不是exp的位置 | \b((?!abc)\w)+\b | 可以匹配不包含连续字符串abc的单词 |
(?<!exp) | 匹配前面不是exp的位置 | (?<![a-z])\d{7} | 匹配前面不是小写字母的七位数字 |
(?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 | 2[0-4]\d(?#200-249)|250-5|[01]?\d\d?(?#0-199) | |
懒惰限定符 | |||
*? | 重复任意次,但尽可能少重复 | a.b ; a.?b | 将正则表达式应用于aabab,前者会匹配整个字符串aabab,后者会匹配aab和ab两个字符串 |
+? | 重复1次或多次,但尽可能少重复 | ||
?? | 重复0次或1次,但尽可能少重复 | ||
{M,N}? | 重复M到N次,但尽可能少重复 | ||
{M,}? | 重复M次以上,但尽可能少重复 |
说明: 如果需要匹配的字符是正则表达式中的特殊字符,那么可以使用\进行转义处理,例如想匹配小数点可以写成\.就可以了,因为直接写.会匹配任意字符;同理,想匹配圆括号必须写成\(和\),否则圆括号被视为正则表达式中的分组。
Python提供了re模块来支持正则表达式相关操作,下面是re模块中的核心函数。
参考:GitHub骆昊Python-100-Days
函数 | 说明 |
---|---|
compile(pattern, flags=0) | 编译正则表达式返回正则表达式对象 |
match(pattern, string, flags=0) | 用正则表达式匹配字符串 成功返回匹配对象 否则返回None |
search(pattern, string, flags=0) | 搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None |
split(pattern, string, maxsplit=0, flags=0) | 用正则表达式指定的模式分隔符拆分字符串 返回列表 |
sub(pattern, repl, string, count=0, flags=0) | 用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count指定替换的次数 |
fullmatch(pattern, string, flags=0) | match函数的完全匹配(从字符串开头到结尾)版本 |
findall(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回字符串的列表 |
finditer(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回一个迭代器 |
purge() | 清除隐式编译的正则表达式的缓存 |
re.I / re.IGNORECASE | 忽略大小写匹配标记 |
re.M / re.MULTILINE | 多行匹配标记 |
说明: 上面提到的re模块中的这些函数,实际开发中也可以用正则表达式对象的方法替代对这些函数的使用,如果一个正则表达式需要重复的使用,那么先通过compile函数编译正则表达式并创建出正则表达式对象无疑是更为明智的选择。
1. 字符串和正则表达式练习
1.1 字符串高级操作练习
1.1.1 字符串常用操作
"""
字符串常用操作
"""
import pyperclip
# 原始字符串
print(r'My brother\'s name is \'007\'')
# 转义字符
print('My brother\'s name is \'007\'')
print('*'*80)
# in/ not in/ is开头判断方法
str = 'hello123world'
print('he' in str)
print('her' not in str)
# 字符串是否只包含字母
print(str.isalpha())
print(str[0:5].isalpha())
# 字符串是否只包含字母和数字
print(str.isalnum())
# 字符串是否只包含数字
print(str.isdecimal())
print(str[5:8].isdecimal())
print('*'*80)
# join用法
list = ['床前明月光', '疑是地上霜', '举头望明月', '低头思故乡']
print('-'.join(list))
print('*'*80)
# split()用法
sentence1 = 'You go your way I will go mine'
sentence2 ='www.google.com'
print(sentence1.split()) # 返回一个列表
print(sentence2.split('.',1))
print('*'*80)
# strip()用法
email = ' jackfrued@126.com'
print(email)
print(email.strip())
print(email.rstrip('.com'))
print('*'*80)
# pyperclip模块用法
# 将文本放入系统剪切板中
pyperclip.copy('老虎不发猫你当我病危呀')
# 从系统剪切板获得文本
print(pyperclip.paste())
My brother\'s name is \'007\'
My brother's name is '007'
********************************************************************************
True
True
False
True
True
False
True
********************************************************************************
床前明月光-疑是地上霜-举头望明月-低头思故乡
********************************************************************************
['You', 'go', 'your', 'way', 'I', 'will', 'go', 'mine']
['www', 'google.com']
********************************************************************************
jackfrued@126.com
jackfrued@126.com
jackfrued@126
********************************************************************************
老虎不发猫你当我病危呀
1.1.2 字符串倒转
"""
字符串常用操作 - 实现字符串倒转的方法
"""
from io import StringIO
def reverse_str1(str):
return str[::-1]
def reverse_str2(str):
if len(str) <= 1:
return str
return reverse_str2(str[1:]) + str[0:1]
def reverse_str3(str):
# StringIO对象是Python中的可变字符串
# 不应该使用不变字符串做字符串连接操作 因为会产生很多无用字符串对象
rstr = StringIO()
str_len = len(str)
for index in range(str_len - 1, -1, -1):
rstr.write(str[index])
return rstr.getvalue()
def reverse_str4(str):
return ''.join(str[index] for index in range(len(str) - 1, -1, -1))
def reverse_str5(str):
# 将字符串处理成列表
str_list = list(str)
str_len = len(str)
# 使用zip函数将两个序列合并成一个产生元组的迭代器
# 每次正好可以取到一前一后两个下标来实现元素的交换
for i, j in zip(range(str_len // 2), range(str_len - 1, str_len // 2, -1)):
str_list[i], str_list[j] = str_list[j], str_list[i]
# 将列表元素连接成字符串
return ''.join(str_list)
if __name__ == '__main__':
str = 'I love Python'
print(str)
print(reverse_str1(str))
print('*'*80)
print(reverse_str2(str))
print('*'*80)
print(reverse_str3(str))
print('*'*80)
print(reverse_str4(str))
print('*'*80)
# print(reverse_str5(str))
I love Python
nohtyP evol I
********************************************************************************
nohtyP evol I
********************************************************************************
nohtyP evol I
********************************************************************************
nohtyP evol I
********************************************************************************
1.2 正则表达式使用练习
1.2.1 验证输入用户名和QQ号是否有效
"""
验证输入用户名和QQ号是否有效并给出对应的提示信息
要求:
用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
QQ号是5~12的数字且首位不能为0
"""
import re
def main():
username = input('请输入用户名: ')
qq = input('请输入QQ号: ')
# match(pattern, string, flags=0)
# 用正则表达式匹配字符串 成功返回匹配对象 否则返回None
m1 = re.match(r'^[0-9a-zA-Z_]{6,20}$', username)
if not m1:
print('请输入有效的用户名.')
m2 = re.match(r'^[1-9]\d{4,11}$', qq)
if not m2:
print('请输入有效的QQ号.')
if m1 and m2:
print('你输入的信息是有效的!')
if __name__ == '__main__':
main()
请输入用户名: fighting
请输入QQ号: 2148924597
你输入的信息是有效的!
1.2.2 从一段文字中提取出国内手机号码
import re
def main():
# 创建正则表达式对象 使用了前瞻和回顾来保证手机号前后不应该出现数字
# compile(pattern, flags=0)编译正则表达式返回正则表达式对象
pattern = re.compile(r'(?<=\D)(1[38]\d{9}|14[57]\d{8}|15[0-35-9]\d{8}|17[678]\d{8})(?=\D)')
sentence = '''
重要的事情说8130123456789遍,我的手机号是13512346789这个靓号,
不是15600998765,也是110或119,王大锤的手机号才是15600998765。
'''
# 查找所有匹配并保存到一个列表中
# findall(pattern, string, flags=0)查找字符串所有与正则表达式匹配的模式 返回字符串的列表
mylist = re.findall(pattern, sentence)
print(mylist)
print('--------华丽的分隔线--------')
# 通过迭代器取出匹配对象并获得匹配的内容
# finditer(pattern, string, flags=0)查找字符串所有与正则表达式匹配的模式 返回一个迭代器
for temp in pattern.finditer(sentence):
print(temp.group())
print('--------华丽的分隔线--------')
# 通过search函数指定搜索位置找出所有匹配
# search(pattern, string, flags=0)搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None
m = pattern.search(sentence)
while m:
print(m.group())
m = pattern.search(sentence, m.end())
if __name__ == '__main__':
main()
['13512346789', '15600998765', '15600998765']
--------华丽的分隔线--------
13512346789
15600998765
15600998765
--------华丽的分隔线--------
13512346789
15600998765
15600998765
1.2.3 不良内容过滤
"""
不良内容过滤
"""
import re
def main():
sentence = '你丫是傻叉吗? 我操你大爷的. Fuck you.'
# sub(pattern, repl, string, count=0, flags=0)用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count指定替换的次数
purified = re.sub('[操肏艹]|fuck|shit|傻[比屄逼叉缺吊屌]|煞笔',
'*', sentence, flags=re.IGNORECASE)
print(purified)
if __name__ == '__main__':
main()
你丫是*吗? 我*你大爷的. * you.
1.2.4 拆分长字符串
import re
def main():
poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
# split(pattern, string, maxsplit=0, flags=0)用正则表达式指定的模式分隔符拆分字符串 返回列表
sentence_list = re.split(r'[,。, .]', poem)
while '' in sentence_list:
sentence_list.remove('')
print(sentence_list)
if __name__ == '__main__':
main()
['窗前明月光', '疑是地上霜', '举头望明月', '低头思故乡']