特别推荐 | “正则表达式”在工业企业数据库匹配中的运用(一)
导读
1.“T T K 家庭电器有限公司”、“3 M 中国有限公司”等含有数字、字母型企业名,中英文符号混乱不一致;
2.还有,武汉旭东食品有限公司的企业名曾出现过“武汉旭东食品公司(2002、2008-2010)”、“武汉旭东食品有限责任公司(2003)”、“武汉市东西湖区旭东食品公司(2004)”和“武汉东西湖旭东食品有限公司(2005-2006)”以及“武汉东西湖旭东食品有限责任公司(2007)”等几种类型;
3.另有“广西横县闵桂钢厂(2003)”与“横县闵桂钢厂(2000-2002、2004-2009)”,地区冠名问题,等等。
”
1、部分企业名称中包含标点符号、数字和字母,而同一企业名称可能由于中英文标点符号、数字和字母不一致会引起样本企业匹配不上。比如,中文符号“【”与英文符号“[”不一致,中英文数字、字母不一致问题等。
2、标点符号统一后,利用企业全称进行精确匹配后,部分无法匹配的企业,可能由于企业名称包含地区冠名信息丢失,如“威海市ABC有限公司”写成“威海ABC有限公司”;或是企业类型发生变更后不一致,像“威海市ABC有限公司”变更“威海市ABC股份有限公司”等诸如此类现象。这时,需要用到企业名称主体进行模糊匹配,尽可能充分提升样本企业识别率。
正则表达式介绍
1、字符串的提取,即从一段文本中提取一个或多个符合正则表达式所代表的文本规则的字符串。(在Python的re库中,有re.search,re.findall等函数可以实现。)
2、字符串的替换,即替换掉一段文本中的一个或多个符合正则表达式所代表的文本规则的字符串。(在Python的re库中,由re.sub函数来执行。)
3、字符串的分割,即将一段文本中的一个或多个以符合正则表达式所代表的文本规则的字符串作为“分隔符”,分成多个小字符串,(在Python的re库中,由re.split函数来执行。)
正则表达式的元字符
In [1]: str0 = """今天去理发,洗剪吹68,烫发和染发668。我就做了个洗剪吹,结账的时候发现居然收我668!!我不服,1米95的经理走出来对我耐心地解释:你看哈,刚才洗头的时候,是不是感觉水很烫??"""
In [2]: re.findall(r'\d', str0) # 加上r模式是为了防止Python中的转义字符与正则表达式中的元字符
Out[2]: ['6', '8', '6', '6', '8', '6', '6', '8', '1', '9', '5']
左右滑动查看更多
In [3]: re.findall('\d+', str0)
Out[3]: ['68', '668', '668', '1', '95']
这就引出了另外一个元字符“+”,“+”在正则表达式里代表的是“匹配前面的子表达式一次或多次”。
In [4]: re.findall('[\d米]+', str0)
Out[4]: ['68', '668', '668', '1米95']
左右滑动查看更多
其实这些元字符还可以进一步分类,限于篇幅我没法介绍很多,大家可以通过这个网址学到更过元字符的用法。
https://www.runoob.com/regexp/regexp-metachar.html
正则表达式的运算符优先级
In [1]: re_str1 = r'[(ABC)(XYZ)]'
In [2]: re_str2 = r'(ABC|XYZ)'
In [3]: str0 = 'ABCXYZ'
In [4]: re.findall(re_str1, str0)
Out[4]: ['A', 'B', 'C', 'X', 'Y', 'Z']
In [5]: re.findall(re_str2, str0)
Out[5]: ['ABC', 'XYZ']
左右滑动查看更多
r'[(ABC)(XYZ)]'
等同于r'[ABCXYZ]'
。这主要是因为方括号“[]”只能匹配一个字符。之前例子中的“\d”中,转义符的优先级高于方括号“[]”。所以程序处理完“\d”后,已经将其视为一个字符了。这是一个初学者比较容易犯的错误(例如当年的我),还请大家引起重视。正则表达式的分组标签
In [1]: str0 = """经过《喜羊羊与灰太狼》全集统计,灰太狼一共被红太狼的平底锅砸过9544次,被喜羊羊捉弄过2347次,被食人鱼追过769次,被电过1755次,捉羊想过2788个办法,奔波过19658次,足迹能绕地球954圈,至今一只羊也没吃到,他并没有放弃,"""
In [2]: re.findall(r'[\d次个圈]+', str0)
Out[2]: ['9544次', '2347次', '769次', '1755次', '2788个', '19658次', '954圈']
左右滑动查看更多
In [3]: re_str = '(?P<平底锅伺候>(?<=平底锅砸过)\d+次)'
In [4]: re.search(re_str, str0).groupdict()
Out[4]: {'平底锅伺候': '9544次'}
In [5]: re_str = '(?P<平底锅伺候>(?<=平底锅砸过)\d+次).*(?P<食人鱼伺候>(?<=食人鱼追过)\d+次)'
In [6]: re.search(re_str, str0).groupdict()
Out[6]: {'平底锅伺候': '9544次', '食人鱼伺候': '769次'}
In [7]: re_str = '平底锅砸过(?P<平底锅伺候>\d+次).*食人鱼追过(?P<食人鱼伺候>\d+次)'
In [8]: re.search(re_str, str0).groupdict()
Out[8]: {'平底锅伺候': '9544次', '食人鱼伺候': '769次'}
(?P<key>pattern)
是正则表达式中的标签语法。圆括号()在正则表达式里代表分组。对应于Python中SRE_Match对象(即re.search返回的对象)下的groups方法,返回的是一个列表。?P<key>
加进去以后,就给这个分组打上标签了。(?<=平底锅砸过)
用到了向后查找lookbehind这个语法,意思就是匹配“平底锅砸过”后面的字符串,不包括“平底锅砸过”这几个字。可惜的是,由于Python的re库的引擎原因,这样的语法中的字符串长度必须是固定长度的。例如,(?<=平底锅\d)
是可以的,四个字符;(?<=平底锅\d\w)
是可以的,五个字符;(?<=平底锅\d+)
就不行了,因为不能确定“+”代表几个字符,在Python中运行的话,会直接报错。但是这个缺陷可以由分组的方式完美避开,参考上面代码中的最后一个正则表达式。
细心的同学可能会发现,上面代码中的最后两个正则表达式,关键词的顺序必须是固定的,即“平底锅”不能出现在“食人鱼”后面。这个是可以通过优化正则表达式来解决的,也是我喜欢用分组标签的一个重要原因,聪明的你知道如何修改吗?在留言区留下你的答案吧!
如何学习正则表达式
图二
►往期推荐
回复【Python】👉简单有用易上手
回复【学术前沿】👉机器学习丨大数据
回复【数据资源】👉公开数据
回复【可视化】👉你心心念念的数据呈现
回复【老姚专栏】👉老姚趣谈值得一看
►一周热文
工具&技巧丨能够融合Stata、Python和R的神器——Jupyter Notebook
工具&技巧 | 经济学圈特供 小刘帮你画专业社会网络图(二)
数据Seminar
这里是大数据、分析技术与学术研究的三叉路口
欢迎扫描👇二维码添加关注