安云网 - AnYun.ORG | 专注于网络信息收集、网络数据分享、网络安全研究、网络各种猎奇八卦。
当前位置: 安云网 > 技术关注 > 编程茶楼 > Python > python中正则表达式的使用详解

python中正则表达式的使用详解

时间:2015-11-06来源:未知 作者:安云网点击:
这篇文章主要介绍了python中正则表达式的使用详解,另附上一些常用的Python正则例子,有需要的朋友可以参考下




原文:http://www.jb51.net/article/56374.htm
//本文来自安云网


//内容来自AnYun.ORG

从学习Python至今,发现很多时候是将Python作为一种工具。特别在文本处理方面,使用起来更是游刃有余。

//内容来自AnYun.ORG

说到文本处理,那么正则表达式必然是一个绝好的工具,它能将一些繁杂的字符搜索或者替换以非常简洁的方式完成。 //内容来自安云网

我们在处理文本的时候,或是查询抓取,或是替换. //copyright AnYun.ORG

一.查找
如果你想自己实现这样的功能模块,输入某一个ip地址,得到这个ip地址所在地区的详细信息.

//安云网,anyun.org

然后你发现http://ip138.com 可以查出很详细的数据 //copyright AnYun.ORG

但是人家没有提供api供外部调用,但是我们可以通过代码模拟查询然后对结果进行抓取. //安云网咨询系统

通过查看这个相应页面的源码,我们可以发现,结果是放在三个<li></li>中的

//安云网,anyun.org

复制代码 代码如下: //内容来自AnYun.ORG


<table width="80%"  border="0" align="center" cellpadding="0" cellspacing="0"> 
    <tr> 
        <td align="center"><h3>ip138.com IP查询(搜索IP地址的地理位置)</h3></td> 
    </tr> 
    <tr> 
        <td align="center"><h1>您查询的IP:121.0.29.231</h1></td> 
    </tr> 
    <tr> 
 
        <td align="center"><ul class="ul1"><li>本站主数据:浙江省杭州市 阿里巴巴</li><li>参考数据一:浙江省杭州市 阿里巴巴</li><li>参考数据二:浙江省杭州市 阿里巴巴</li></ul></td> 

//本文来自安云网


    </tr> 
    <tr> 
        <td align="center">如果您发现查询结果不详细或不正确,请使用<a href="ip_add.asp?ip=121.0.29.231"><font color="#006600"><b>IP数据库自助添加</b></font></a>功能 进行修正<br/><br/> 
        <iframe src="/jss/bd_460x60.htm" frameborder="no" width="460" height="60" border="0" marginwidth="0" marginheight="0" scrolling="no"></iframe><br/><br/></td> 
 
    </tr> 
    <form method="get" action="ips8.asp" name="ipform" onsubmit="return checkIP();"> 
    <tr> 
        <td align="center">IP地址或者域名:<input type="text" name="ip" size="16"> <input type="submit" value="查询"><input type="hidden" name="action" value="2"></td> 
//ANYUN.ORG

    </tr><br> 
<br> 
    </form> 
</table>   

//copyright AnYun.ORG

如果你了解正则表达式你可能会写出

//安云网,anyun.org

正则表达式 //内容来自AnYun.ORG

复制代码 代码如下: //copyright AnYun.ORG


(?<=<li>).*?(?=</li>)
//内容来自AnYun.ORG

这里使用了前瞻:lookahead 后顾: lookbehind,这样的好处就是匹配的结果中就不会包含html的li标签了. //copyright AnYun.ORG

如果你对自己写的正则表达式不是很自信的话,可以在一些在线或者本地的正则测试工具进行一些测试,以确保正确. //copyright AnYun.ORG

接下来的工作就是如果用Python实现这样的功能,首先我们得将正则表达式表示出来: //安云网咨询系统

复制代码 代码如下: //copyright AnYun.ORG


r"(?<=<li>).*?(?=</li>)" 
//内容来自AnYun.ORG

 Python中字符串前面加上前导r这个字符,代表这个字符串是R aw String(原始字符串),也就是说Python字符串本身不会对字符串中的字符进行转义.这是因为正则表达式也有转义字符之说,如果双重转义的话,易读性很差. //内容来自AnYun.ORG

这样的串在Python中我们把它叫做"regular expression pattern"

//内容来自安云网

如果我们对pattern进行编译的话 //安云网,anyun.org

复制代码 代码如下: //安云网咨询系统


prog = re.compile(r"(?<=<li>).*?(?=</li>)") 
//内容来自安云网

我们便可以得到一个正则表达式对象regular expression object,通过这个对象我们可以进行相关操作. //内容来自AnYun.ORG

比如 //内容来自安云网

复制代码 代码如下: //内容来自AnYun.ORG


result=prog.match(string) 
##这个等同于 
result=re.match(r"(?<=<li>).*?(?=</li>)",string) 
##但是如果这个正则需要在程序匹配多次,那么通过正则表达式对象的方式效率会更高 

//本文来自安云网

接下来就是查找了,假设我们的html结果已经以html的格式存放在text中,那么通过

//ANYUN.ORG

复制代码 代码如下:

//本文来自安云网


result_list = re.findall(r"(?<=<li>).*?(?=</li>)",text) 
//安云网,anyun.org

便可以取得所需的结果列表. //本文来自安云网

二.替换
使用正则表达式进行替换非常的灵活. //copyright AnYun.ORG

比如之前我在阅读Trac这个系统中wiki模块的源代码的时候,就发现其wiki语法的实现就是通过正则替换进行的. //内容来自AnYun.ORG

在使用替换的时候会涉及到正则表达式中的Group分组的概念. //安云网,anyun.org

假设wiki语法中使用!表示转义字符即感叹号后面的功能性字符会原样输出,粗体的语法为

//安云网,anyun.org

写道
'''这里显示为粗体'''
 那么有正则表达式为 //安云网咨询系统

复制代码 代码如下:

//copyright AnYun.ORG


r"(?P<bold>!?''')" 

//内容来自AnYun.ORG

  这里的?P<bold>是Python正则语法中的一部分,表示其后的group的名字为"bold"

//内容来自AnYun.ORG

  下面是替换时的情景,其中sub函数的第一个参数是pattern,第二个参数可以是字符串也可以是函数,如果是字符串的话,那么就是将目标匹配的结果替 换成指定的结果,而如果是函数,那么函数会接受一个match object的参数,并返回替换后的字符串,第三个参数便是源字符串. //ANYUN.ORG

复制代码 代码如下:

//内容来自AnYun.ORG


result = re.sub(r"(?P<bold>!?''')", replace, line) 

//copyright AnYun.ORG

每当匹配到一个三单引号,replace函数便运行一次,可能这时候需要一个全局变量记录当前的三单引号是开还是闭,以便添加相应的标记. //安云网咨询系统

在实际的trac wiki的实现的时候,便是这样通过一些标记变量,来记录某些语法标记的开闭,以决定replace函数的运行结果.

//内容来自AnYun.ORG

--------------------

//安云网,anyun.org

示例 //ANYUN.ORG

一. 判断字符串是否是全部小写 //内容来自安云网

代码

//安云网咨询系统

复制代码 代码如下: //内容来自安云网


# -*- coding: cp936 -*-
import re 
s1 = 'adkkdk'
s2 = 'abc123efg' //内容来自安云网

an = re.search('^[a-z]+$', s1)
if an:
    print 's1:', an.group(), '全为小写'
else:
    print s1, "不全是小写!" //copyright AnYun.ORG

an = re.match('[a-z]+$', s2)
if an:
    print 's2:', an.group(), '全为小写'
else:
    print s2, "不全是小写!"
//本文来自安云网

结果 //本文来自安云网

 

//内容来自AnYun.ORG

究其因

//内容来自AnYun.ORG

1. 正则表达式不是python的一部分,利用时需要引用re模块 //内容来自AnYun.ORG

2. 匹配的形式为: re.search(正则表达式, 带匹配字串)或re.match(正则表达式, 带匹配字串)。两者区别在于后者默认以开始符(^)开始。因此,

//安云网咨询系统

re.search('^[a-z]+$', s1) 等价于 re.match('[a-z]+$', s2)
3. 如果匹配失败,则an = re.search('^[a-z]+$', s1)返回None //内容来自安云网

group用于把匹配结果分组

//ANYUN.ORG

例如

//安云网咨询系统

复制代码 代码如下:

//ANYUN.ORG


import re
a = "123abc456"
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0)   #123abc456,返回整体
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1)   #123
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2)   #abc
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3)   #456

//本文来自安云网

1)正则表达式中的三组括号把匹配结果分成三组

//本文来自安云网

  group() 同group(0)就是匹配正则表达式整体结果

//本文来自安云网

  group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。

//本文来自安云网

2)没有匹配成功的,re.search()返回None //内容来自安云网

3)当然郑则表达式中没有括号,group(1)肯定不对了。 //内容来自AnYun.ORG

二.  首字母缩写词扩充

//ANYUN.ORG

具体示例 //ANYUN.ORG

FEMA   Federal Emergency Management Agency
IRA    Irish Republican Army
DUP    Democratic Unionist Party

//安云网,anyun.org

FDA    Food and Drug Administration
OLC    Office of Legal Counsel
分析

//安云网咨询系统

缩写词  FEMA
分解为  F*** E*** M*** A***
规律    大写字母 + 小写(大于等于1个)+ 空格
参考代码

//安云网,anyun.org

复制代码 代码如下:

//内容来自安云网


import re
def expand_abbr(sen, abbr):
    lenabbr = len(abbr)
    ma = ''
    for i in range(0, lenabbr):
        ma += abbr[i] + "[a-z]+" + ' '
    print 'ma:', ma
    ma = ma.strip(' ')
    p = re.search(ma, sen)
    if p:
        return p.group()
    else:
        return '' //ANYUN.ORG

print expand_abbr("Welcome to Algriculture Bank China", 'ABC')

//内容来自安云网

结果

//安云网,anyun.org

//内容来自安云网

问题 //ANYUN.ORG

上面代码对于例子中的前3个是正确的,但是后面的两个就错了,因为大写字母开头的词语之间还夹杂着小写字母词 //copyright AnYun.ORG

规律 //copyright AnYun.ORG

大写字母 + 小写(大于等于1个)+ 空格 + [小写+空格](0次或1次)

//安云网咨询系统

参考代码

//安云网咨询系统

复制代码 代码如下: //ANYUN.ORG


import re
def expand_abbr(sen, abbr):
    lenabbr = len(abbr)
    ma = ''
    for i in range(0, lenabbr-1):
        ma += abbr[i] + "[a-z]+" + ' ' + '([a-z]+ )?'
    ma += abbr[lenabbr-1] + "[a-z]+"
    print 'ma:', ma
    ma = ma.strip(' ')
    p = re.search(ma, sen)
    if p:
        return p.group()
    else:
        return '' //内容来自AnYun.ORG

print expand_abbr("Welcome to Algriculture Bank of China", 'ABC')

//内容来自安云网

技巧 //内容来自安云网

中间的 小写字母集合+一个空格,看成一个整体,就加个括号。要么同时有,要么同时没有,这样需要用到?,匹配前方的整体。

//安云网咨询系统

三. 去掉数字中的逗号

//copyright AnYun.ORG

具体示例 //内容来自AnYun.ORG

在处理自然语言时123,000,000如果以标点符号分割,就会出现问题,好好的一个数字就被逗号肢解了,因此可以先下手把数字处理干净(逗号去掉)。 //copyright AnYun.ORG

分析 //内容来自安云网

数字中经常是3个数字一组,之后跟一个逗号,因此规律为:***,***,*** //内容来自AnYun.ORG

正则式

//本文来自安云网

[a-z]+,[a-z]?

//内容来自安云网

参考代码3-1

//copyright AnYun.ORG

复制代码 代码如下:

//ANYUN.ORG


import re //内容来自安云网

sen = "abc,123,456,789,mnp"
p = re.compile("\d+,\d+?")

//ANYUN.ORG

for com in p.finditer(sen):
    mm = com.group()
    print "hi:", mm
    print "sen_before:", sen
    sen = sen.replace(mm, mm.replace(",", ""))
    print "sen_back:", sen, '\n'
//内容来自安云网

结果

//安云网,anyun.org

//copyright AnYun.ORG

技巧

//copyright AnYun.ORG

使用函数finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]): //安云网,anyun.org

搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。     

//ANYUN.ORG

参考代码3-2 //ANYUN.ORG

复制代码 代码如下: //本文来自安云网


sen = "abc,123,456,789,mnp"
while 1:
    mm = re.search("\d,\d", sen)
    if mm:
        mm = mm.group()
        sen = sen.replace(mm, mm.replace(",", ""))
        print sen
    else:
        break

//本文来自安云网

结果

//ANYUN.ORG

//安云网,anyun.org

延伸 //安云网,anyun.org

这样的程序针对具体问题,即数字3位一组,如果数字混杂与字母间,干掉数字间的逗号,即把“abc,123,4,789,mnp”转化为“abc,1234789,mnp”

//ANYUN.ORG

思路

//本文来自安云网

更具体的是找正则式“数字,数字”找到后用去掉逗号的替换

//ANYUN.ORG

参考代码3-3

//内容来自AnYun.ORG

复制代码 代码如下: //ANYUN.ORG


sen = "abc,123,4,789,mnp"
while 1:
    mm = re.search("\d,\d", sen)
    if mm:
        mm = mm.group()
        sen = sen.replace(mm, mm.replace(",", ""))
        print sen
    else:
        break
print sen

//本文来自安云网

结果

//安云网咨询系统

//内容来自AnYun.ORG

四. 中文处理之年份转换(例如:一九四九年--->1949年) //ANYUN.ORG

中文处理涉及到编码问题。例如下边的程序识别年份(****年)时 //ANYUN.ORG

复制代码 代码如下: //安云网咨询系统


# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中国成立"
m1 =  "比一九九零年低百分之五点二"
m2 =  '人一九九六年击败俄军,取得实质独立' //ANYUN.ORG

def fuc(m):
    a = re.findall("[零|一|二|三|四|五|六|七|八|九]+年", m)
    if a:
        for key in a:
            print key
    else:
        print "NULL"

//copyright AnYun.ORG

fuc(m0)
fuc(m1)
fuc(m2)
//本文来自安云网

运行结果 //安云网咨询系统

//内容来自安云网

可以看出第二个、第三个都出现了错误。 //内容来自安云网

改进——准化成unicode识别 //内容来自安云网

复制代码 代码如下: //内容来自安云网


# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中国成立"
m1 =  "比一九九零年低百分之五点二"
m2 = '人一九九六年击败俄军,取得实质独立' //ANYUN.ORG

def fuc(m):
    m = m.decode('cp936')
    a = re.findall(u"[\u96f6|\u4e00|\u4e8c|\u4e09|\u56db|\u4e94|\u516d|\u4e03|\u516b|\u4e5d]+\u5e74", m)

//ANYUN.ORG

    if a:
        for key in a:
            print key
    else:
        print "NULL" //copyright AnYun.ORG

fuc(m0)
fuc(m1)
fuc(m2)

//内容来自AnYun.ORG

结果

//copyright AnYun.ORG

//安云网,anyun.org

识别出来可以通过替换方式,把汉字替换成数字。 //内容来自安云网

参考

//ANYUN.ORG

复制代码 代码如下: //ANYUN.ORG


numHash = {}
numHash['零'.decode('utf-8')] = '0'
numHash['一'.decode('utf-8')] = '1'
numHash['二'.decode('utf-8')] = '2'
numHash['三'.decode('utf-8')] = '3'
numHash['四'.decode('utf-8')] = '4'
numHash['五'.decode('utf-8')] = '5'
numHash['六'.decode('utf-8')] = '6'
numHash['七'.decode('utf-8')] = '7'
numHash['八'.decode('utf-8')] = '8'
numHash['九'.decode('utf-8')] = '9'

//安云网,anyun.org

def change2num(words):
    print "words:",words
    newword = ''
    for key in words:
        print key
        if key in numHash:
            newword += numHash[key]
        else:
            newword += key
    return newword

//内容来自安云网

def Chi2Num(line):
    a = re.findall(u"[\u96f6|\u4e00|\u4e8c|\u4e09|\u56db|\u4e94|\u516d|\u4e03|\u516b|\u4e5d]+\u5e74", line)
    if a:
        print "------"
        print line
        for words in a:
            newwords = change2num(words)
            print words
            print newwords
            line = line.replace(words, newwords)
    return line

//安云网咨询系统

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
验证码: 点击我更换图片
相关内容
推荐内容