python入门--正则表达式

问题:假设你有一个无聊的任务,要在很长的文章中,找出所有的电话号码和邮件地址。如果手动翻页,那可能需要很长时间。若果你有一个程序,可以在剪切板的文本中查找电话号码和email地址,那你只用按下cltr+a全选所有文本,然后拷贝到剪切板上,它会用找到的电话号码和email地址替换掉剪切板上的文本。

目的:

1.从剪切板取得文本

2.找出文本中所有的电话号码

3.将它们粘贴到剪切板

如何做:

1.使用pyperclip模块复制和粘贴字符串

2.创建两个正则表达式,找到所有匹配的内容

3.整理匹配的字符串,放在一个字符串中,用于粘贴

4.如果文本中没有匹配字符串,则返回提示消息

step1:为电话号码创建一个正则表达式

# -*- coding: UTF-8 -*-
# author :ray


import pyperclip,re

#创建一个正则表达式来匹配电话号码(可能含分机)
phoneRegex =re.compile(r'''
    (\d{3}|\(\d{3}\))?              #区号
    (\s|-|\.)?                      #分隔符
    (\d{3})                         #前三个数字
    (\s|-|\.)                       #分隔符
    (\d{4])                         #最后四个数字
    (\s*(ext|x|ext\.)\s*(\d{2,5}))? #分机号
    ''',re.VERBOSE)

#创建一个正则表达式来匹配email地址
emailRegex = re.compile(r'''(
    [a-zA-Z0-9._%+-]+               #用户名
    @                               #@标记
    [a-zA-Z0-9.-]+                  #域名
    (\.[a-zA-Z]{2,4})               #.something
    )''', re.VERBOSE)

#在剪切板中找到所有匹配
text = str(pyperclip.paste())
matches= []
for groups in phoneRegex.findall(text):
    phoneNum = '_'.join([groups[1],groups[3],groups[5]])
    if groups[8] !='':
        phoneNum +=' x' +groups[8]
    matches.append(phoneNum)
for groups in emailRegex.findall(text):
    matches.append(groups[0])

#将所有匹配连成字符串,复制到剪切板
if len(matches)>0:
    pyperclip.copy('\n'.join(matches))
    print('Copied to clipboard:')
    print('\n'.join(matches))
else:
    print('No phone numbers or emails addresses found.')
/Users/mac/anaconda3/bin/python /Users/mac/PycharmProjects/Mine/reg/phoneAndEmail.py
Copied to clipboard:
[email protected]
[email protected]
[email protected]
[email protected]

这里电话没有匹配出来,是因为网站上的电话格式修改了。稍后修改下phoneRegex匹配。

现在先回顾一下正则表达式的学习:

在python中使用正则表达式有如下步骤:

1.import re
2.用re.compile()函数创建Regex对象(即re.compile()的返回值为一个Regex对象)
3.对Regex对象使用search()方法,并传入想查询的字符串,返回一个Match对象
3.调用Match对象的group()方法,返回匹配的文本

以"my number is 415-555-4242."为例
欲匹配这个字符串中的电话号码可以使用如下几种正则表达式:
1.numRegex = re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d')这是最简单也是最傻的方法,刚才写的时候都觉得自己很傻
2.numRegex = re.compile(r'\d{3}-\d{4}-\d{4}')用花括号(大括号)匹配特定次数
3.numRegex = re.compile(r'(\d{3})-(\d{4})-(\d{4})')这里是仅仅是利用括号分组,分组之后可以一次性获取所有的分组
>>> phoneRegex = re.compile(r'(\d{3})-(\d{4})-(\d{4})')
>>> phone = phoneRegex.search('my phone numbers is 415-5554-2222')
>>> phone.group()
'415-5554-2222'
>>> phone.groups()
('415', '5554', '2222')
这里也可以将分组中的值赋给数目相同变量

其中用花括号匹配特定次数时,花括号内可以有两个参数,也可以只有一个参数.
如:{a,b}、{a,}、{,b}
分别表示匹配次数为a-b、a-~、0-b

正则表达式的匹配模式:
附:我们知道python的正则表达式的匹配是贪心的,也即当同样两个文本匹配时,它会输出较长的文本

1.用|匹配多个分组:也就是匹配|两侧的表达式均可,但是在返回时会优先输出先匹配的字符
如:nameRegex = re.compile(r'ray|lei')当我们对这个Regex对象使用search方法输入一段字符时,
若文本中包含ray和lei,先出现ray则最后输出为ray,若先出现lei,则输出lei

2.可以用?表示问号前面的表达式是否匹配是可选的,例:
nameRegex = re.compile(r'\d-?')也就是说对regex对象使用search方法传入字符串时,数字后有无-是不重要的

3.与2类似的用法,可以用*匹配0次或者多次

4.与2类似的用法,可以用+匹配一次或者多次

5. 点号.可以匹配除换行符外所有的单个字符,它的特殊用法是.*用来匹配所有字符

5.注意:当真正要匹配|、?、*、+、.时可以使用\|,\?\*\+\.来匹配它们

对Regex对象而言它包含以下方法:
1.search(),这个已经讲的很明白了,返回的是被查找字符串中的第一次匹配的文本。

2.findall()它用来查找字符串中的所有匹配。
使用时注意一点:
当表达式中未使用()分组时,返回的结果是一个字符串列表。
而当表达式中使用()分组时,返回的事元组的列表。[(),(),()]


字符分类:
\d:匹配0-9的任意数字
\D:匹配任意除0-9的数字
\w:匹配任何字母、数字、下划线的字符(记做word)
\W:匹配任何除字母、数字、下划线的字符
\s:匹配空格、制表符、换行符(记做空白字符)
\S:匹配除空格、制表符、换行符外的任何字符


当我们建立一个Regex对象时,会写正则表达式,你可以用以上所有介绍过的匹配方式表示你所想匹配的模型,
也可以使用[]定义自己的字符分类,通常在[]左边加上一个插入字符^即^[]表示匹配除[]内的以外的所有字符

在正则表达式的开始处可以使用插入符号^,表示匹配必须发生在被查找文字的开头出,也就是字符串首部要与你的匹配模式相同
同样的,在表达式的最后可以使用美元符$,表示必须以它前面的正则表达式结束。

特殊的当你的正则表达式同时包含^和$时,表明对Regex对象使用search方法时传入的字符串必须满足整个正则表达式

我们在创建Regex对象时,需要向re.compile()方法同时传入第二个参数:re.DOTALL
例如:re.compile(r'.*',re.DOTALL)


当正则表达式指定匹配文本的大小写
当不在乎匹配的字符串的大小写时,可以在建立Regex对象时,向re.compile()中传入第二个参数re.I
python中向re.compile()并不允许传入多余两个以上的参数,有必要时,使用|符号.

刚才写完了去洗澡回来发现之前的phoneRegex匹配没有解决。上图看一下它的电话格式是如何


这里修改下phoneRegex正则表达式里的连字符发现文章开头的部分代码错误:先修正如下:


然后此处电话的形式有些看不习惯,原因是在遍历剪切板内容时,findall()方法返回的是包含每个元组内包含五个字符的列表,在循环中打错字符用“_”,导致"".join()方法连接时出现问题。

晚些时间会再写一篇博客记录正则表达式习题的问题。

猜你喜欢

转载自blog.csdn.net/LawenceRay/article/details/79980236