会用到的语法

正则字符

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

释义

举例

+

前面元素至少出现一次

ab+:ab、abbbb 等

*

前面元素出现0次或多次

ab*:a、ab、abb 等

?

匹配前面的一次或0次

Ab?: A、Ab 等

^

作为开始标记

^a:abc、aaaaaa等

$

作为结束标记

c$:abc、cccc 等

\d

数字

3、4、9 等

\D

非数字

A、a、- 等

[a-z]

A到z之间的任意字母

a、p、m 等

[0-9]

0到9之间的任意数字

0、2、9 等

注意:

1. 转义字符

正则表达式题 随笔 第1张
1 2 3 4 5 >>> s '(abc)def' >>> m  =  re.search( "(\(.*\)).*" , s) >>>  print  m.group( 1 ) (abc)

  

正则表达式题 随笔 第2张

group()用法参考

2. 重复前边的字串多次

1 2 3 4 5 6 7 8 9 10 11 12 13 import  re   =  "kdla123dk345" =  "kdla1123345" =  re.search( "([0-9]+(dk){0,1})[0-9]+" , a) print  (m.group( 0 ),m.group( 1 ),m.group( 2 )) =  re.search( "([0-9]+(dk){0,1})[0-9]+" , b) print  (m.group( 0 ),m.group( 1 ),m.group( 2 ))       123dk345  123dk  dk   1123345  112334  None      #group(1) 截获了多次的组返回最后一次截获的子串。

  

示例

回到顶部

一. 判断字符串是否是全部小写

代码

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import  re   s1  =  'adkkdk' s2  =  'abc123efg'   an  =  re.search( '^[a-z]+$' , s1) if  an:      print  ( 's1:' , an.group(),  '全为小写' ) else :      print  (s1,  "不全是小写!" )   an  =  re.match( '[a-z]+$' , s2) if  an:      print  ( 's2:' , an.group(),  '全为小写' ) else :      print  (s2,  "不全是小写!" )     s1: adkkdk 全为小写 abc123efg 不全是小写!

  

 

究其因

1. 正则表达式不是python的一部分,利用时需要引用re模块

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

re.search('^[a-z]+$', s1) 等价于 re.match('[a-z]+$', s2)

3. 如果匹配失败,则an = re.search('^[a-z]+$', s1)返回None

group用于把匹配结果分组

例如

正则表达式题 随笔 第3张 正则表达式题 随笔 第4张
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
正则表达式题 随笔 第5张 正则表达式题 随笔 第6张

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

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

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

2)没有匹配成功的,re.search()返回None

3)当然郑则表达式中没有括号,group(1)肯定不对了。

回到顶部

二.  首字母缩写词扩充

具体示例

FEMA   Federal Emergency Management Agency
IRA    Irish Republican Army
DUP    Democratic Unionist Party
FDA Food and Drug Administration OLC Office of Legal Counsel

分析

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

参考代码

正则表达式题 随笔 第7张 正则表达式题 随笔 第8张
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 ''

print expand_abbr("Welcome to Algriculture Bank China", 'ABC')
正则表达式题 随笔 第9张 正则表达式题 随笔 第10张

结果

正则表达式题 随笔 第11张

问题

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

规律 

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

参考代码

正则表达式题 随笔 第12张 正则表达式题 随笔 第13张
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 ''

print expand_abbr("Welcome to Algriculture Bank of China", 'ABC')
正则表达式题 随笔 第14张 正则表达式题 随笔 第15张

技巧

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

回到顶部

三. 去掉数字中的逗号

具体示例

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

分析

数字中经常是3个数字一组,之后跟一个逗号,因此规律为:***,***,***

正则式

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

参考代码3-1

正则表达式题 随笔 第16张 正则表达式题 随笔 第17张
import re

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

for com in p.finditer(sen): #搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。 
    mm = com.group()
    print "hi:", mm
    print "sen_before:", sen
    sen = sen.replace(mm, mm.replace(",", ""))
    print "sen_back:", sen, '\n'
正则表达式题 随笔 第18张 正则表达式题 随笔 第19张

结果

正则表达式题 随笔 第20张

技巧

使用函数finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):

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

参考代码3-2

正则表达式题 随笔 第21张 正则表达式题 随笔 第22张
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
正则表达式题 随笔 第23张 正则表达式题 随笔 第24张

结果

正则表达式题 随笔 第25张

延伸

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

思路

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

参考代码3-3

正则表达式题 随笔 第26张 正则表达式题 随笔 第27张
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
正则表达式题 随笔 第28张 正则表达式题 随笔 第29张

结果

正则表达式题 随笔 第30张

回到顶部

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

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

正则表达式题 随笔 第31张 正则表达式题 随笔 第32张
# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中国成立"
m1 =  "比一九九零年低百分之五点二"
m2 =  '人一九九六年击败俄军,取得实质独立'

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

fuc(m0)
fuc(m1)
fuc(m2)
正则表达式题 随笔 第33张 正则表达式题 随笔 第34张

运行结果

正则表达式题 随笔 第35张

可以看出第二个、第三个都出现了错误。

改进——准化成unicode识别

正则表达式题 随笔 第36张 正则表达式题 随笔 第37张
# -*- coding: cp936 -*-
import re
m0 =  "在一九四九年新中国成立"
m1 =  "比一九九零年低百分之五点二"
m2 = '人一九九六年击败俄军,取得实质独立'

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

    if a:
        for key in a:
            print key
    else:
        print "NULL"

fuc(m0)
fuc(m1)
fuc(m2)
正则表达式题 随笔 第38张 正则表达式题 随笔 第39张

结果

正则表达式题 随笔 第40张

识别出来可以通过替换方式,把汉字替换成数字。

参考

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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'   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):      =  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

有一个文件,文件名为output_1981.10.21.txt 。下面使用Python: 读取文件名中的日期时间信息,并找出这一天是周几。将文件改名为output_YYYY-MM-DD-W.txt (YYYY:四位的年,MM:两位的月份,DD:两位的日,W:一位的周几,并假设周一为一周第一天)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import  re  import  time  import  datetime      filename  =  "output_1981.10.21.txt"  =  re.search( "output_(\d{4}.\d{2}.\d{2})" , filename)  searchResult  =  m.group( 1 print  ( "matcht result: %s"  %  searchResult)  dates  =  searchResult.split( '.' for  date  in  dates:       print  date  year  =  dates[ 0 month  =  dates[ 1 day  =  dates[ 2 xingqi  =  datetime.datetime( int (year),  int (month),  int (day)).strftime( "%w" # replace to new filename  theReplacePart  =  '%s-%s-%s-%s'  %  (year,month,day,xingqi)  print  'the new filename is: %s'  %  theReplacePart  newfileName  =  re.sub( "\d{4}.\d{2}.\d{2}" , theReplacePart, filename)  print  newfileName 

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄