python正则简介

正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。python提供一个re模块来使用正则表达式,re 模块使 Python 语言拥有全部的正则表达式功能。

常用的正则表达式(代更新)

[0-9]或者‘\d’ 匹配一个数字字符;

[^0-9] 或者'\D' 匹配一个非数字字符;

'\s' 匹配任何的空白字符 '\s{2,}'匹配任何大于2个的空白字符;

'\S' 匹配任何非空白字符;

[0-9a-zA-Z_] 或者 '\w' 匹配一个数字、字母或者下划线;

[^0-9a-zA-Z_] 或者·'W' 匹配任何非单词字符;

^表示行的开头,'^\d' 表示必须以数字开头;

$表示行的结束,'\d$' 表示必须以数字结束;

'[\u4e00-\u9fa5]+' 匹配所有的中文字符

python的re模块常用函数说明

re.match(pattern, string, flags=0) 从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none,匹配成功返回match对象

import re
print(re.match(r'^\d{3}\-\d{3,8}$', '010-12345'))
print(re.match(r'^\d{3}\-\d{3,8}$', '010 12345'))
print(re.match('www', 'www.baidu.com'))
output:
None

re.split(pattern, string, max = 0) 根据正则表达式的模式分隔符,split函数将字符串分割为列表,返回匹配列表,分割最多操作max次

import re

print('a b c'.split(' '))##普通字符串分割无法区分连续空格

print(re.split(r'\s+','a b c'))## 使用正则模式分隔符,多个空格也可以分

print(re.split(r'[\s\,]+', 'a,b, c , d'))##多个空格加上','

print(re.split(r'[\s\,\:\?\;]+', 'a,b, c , : ? d ; : ee')) ##加上多个分隔符

output:
['a', 'b', '', '', 'c']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['a', 'b', 'c', 'd', 'ee']

re.compile(pattern, flags = 0) 预编译该正则表达式

当我们在Python中使用正则表达式时,re模块内部会干两件事情:

1、编译正则表达式,如果正则表达式的字符串本身不合法,会报错;

2、用编译后的正则表达式去匹配字符串;

为了使用效率,我们往往会预编译一些正则表达式;

import re
re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
print(re_telephone.match('010-12345').groups())
print(re_telephone.match('010-8086').group(0))
output:
('010', '12345')
010-8086

re.findall(pattern, string[,flags] ) 查找字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表

import re
a = "java|python12988"
print(re.findall("java", a))
print(re.findall("\d+",a))
output:
['java']
['12988']

re.sub(要替换的字符,替换后字符,目标字符串,替换个数) 正则替换,返回值为替换后的字符串

import re
language = 'PythonC#JavaC#PHPC#'
r = re.sub(r'C#+','GO',language)
print(r)
output:
PythonGOJavaGOPHPGO

python 正则实例分析

从一段字符串中匹配出中文字符,并且分割成列表(方法一)

'''从一段字符串中匹配出中文字符,并且分割成列表(方法一)'''

def translate(str):
line = str.strip()
pattern = re.compile('[^\u4e00-\u9fa5]+')
# zh = " ".join(pattern.split(line)).strip()
zh = ' '.join(pattern.split(line)).strip().split()
return zh
string = '"doc_count": 266\n}\n]\n}\n},\n{\n"key": "郭伟",\n"doc_count":"张三" 232,\n"year_agg": {\n'
translate(string)
output:
['郭伟', '张三']
'''从一段字符串中匹配出中文字符,并且分割成列表(方法二)'''
string = '"doc_count": 266\n}\n]\n}\n},\n{\n"key": "郭伟","郭伟"\n"doc_count":"张三" 232,\n"year_agg": {\n'
list(set(re.findall(r'[\u4e00-\u9fa5]+',string)))
output:
['郭伟', '张三']

尝试写一个验证Email地址的正则表达式。版本一应该可以验证出类似的Emailsomeone@gmail.com

bill.gates@microsoft.com
wss9642@163.com
import re
def is_valid_email(addr):
re_valid_email=re.compile(r'^([0-9a-zA-Z\_\.\s]+)@(\w+).(\w{3,})$')
if re_valid_email.match(addr):
print('email 符合规则')
else:
print('email 不符合规则')
is_valid_email('wss9642@163.com')
is_valid_email('1310964429@qq.com')
is_valid_email('bill.gates@microsoft.com')
is_valid_email('1310964429@qq.cn')
is_valid_email('bob#example.com')
is_valid_email('mr-bob@example.com')
output:
email 符合规则
email 符合规则
email 符合规则
email 不符合规则
email 不符合规则
email 不符合规则

使用re正则表达式,从一段规则文本中提取需求的数据转化为一定的格式(将论文关键词转化为关系记录模式)

具体需要利用正则处理的文本数据如下:


import re
import pandas as pd
import datetime
print('start')
file=pd.read_csv('G:/测试数据/测试结果/AMIN_paper_title_0.csv',encoding='utf-8')
file = file.iloc[0:1000,:]
start = datetime.datetime.now()
'''使用iterrows()迭代'''
def pd_byiterrows(file):
index_value=0
df =pd.DataFrame(columns=(':START_ID',':END_ID','VALUE',':TYPE'))
for i in file[['paper_id','keyword_list']].iterrows():
#value=re.findall(r'\d+\.\w+',i[1]['keyword_list'])
#keyword=[]
for m in re.findall(r'\((.*?)\)',i[1]['keyword_list']):
tx=m.split(',')
if len(tx)==2 and float(tx[1])>0.8 and tx[0]!='nan' and not ('\u4e00' <= tx[0].replace('\'','') <= '\u9fa5') and bool(re.search('[a-z]', tx[0].replace('\'',''))) and not bool(re.match(r'[0-9]+', tx[0].replace('\'',''))):
index_value+=1
df1 = pd.DataFrame({':START_ID': i[1]['paper_id'],':END_ID': tx[0].replace('\'',''),'VALUE':float(tx[1]),':TYPE':'theme_word'},index=[index_value])
df = df.append(df1)
else:
continue
return df
'''使用itertuples迭代,一般来说itertuples迭代速度要快与iterrows()'''
def pd_byitertuples(file):
index_value=0
df =pd.DataFrame(columns=(':START_ID',':END_ID','VALUE',':TYPE'))
for i in file[['paper_id','keyword_list']].itertuples():
#value=re.findall(r'\d+\.\w+',i[1]['keyword_list'])
for m in re.findall(r'\((.*?)\)',getattr(i, 'keyword_list')):
tx=m.split(',')
# if ('\u4e00' <= tx[0].replace('\'','') <= '\u9fa5') or not bool(re.search('[a-z]', tx[0].replace('\'',''))) or bool(re.match(r'[0-9]', tx[0].replace('\'',''))):
# print(tx[0])
if len(tx)==2 and float(tx[1])>0.8 and tx[0]!='nan' and not ('\u4e00' <= tx[0].replace('\'','') <= '\u9fa5') and bool(re.match('[a-z]', tx[0].replace('\'',''))) and not bool(re.match(r'[0-9]+', tx[0].replace('\'',''))):
index_value+=1
df1 = pd.DataFrame({':START_ID': getattr(i, 'paper_id'),':END_ID': tx[0].replace('\'',''),'VALUE':float(tx[1]),':TYPE':'theme_word'},index=[index_value])
# print(df1)
df = df.append(df1)
else:
continue
return df
print(re.sub(r'[^\w\-]','',re.findall(r'\((.*?)\)',file['keyword_list'][1])[0].split(',')[0]))
df = pd_byiterrows(file)

print('使用iterrows()迭代数据帧花费时间:',datetime.datetime.now()-start)

df1 = pd_byitertuples(file)

print('使用itertuples迭代数据帧花费时间:',datetime.datetime.now()-start)

具体的输出结果如下:

runfile('C:/Users/13109/.spyder-py3/temp.py', wdir='C:/Users/13109/.spyder-py3')
start
one-dimensional

使用iterrows()迭代数据帧花费时间: 0:00:07.907672

使用itertuples迭代数据帧花费时间: 0:00:15.517259