这两天在写爬虫程序,涉及英文文本处理,需要规范化英文标点符号的写法。正常情况下,英文句号「.」后面需要保证有且只有一个空格,但也有例外情况,比如「i.e.」、「e.g.」、「P.S.」这种。由于无法预测大小写,因此在正则表达式中使用了「标志位」flags,却死活不生效。

一开始,我的函数是这样写的:

1 def punctuate(s):
2 #----其余代码暂略
3 s = re.sub(' e. g. ', 'e.g.', s, re.I)
4 return s

代码的本意是:本来好好的「e.g.」,被函数前半断的代码错改成「e. g. 」之后,需要修复一下,将英文句号「.」后面的空格删掉。但这行 re.sub() 代码主要有2个问题:

  1. 「e. g.」前后不一定是空格,因此这样写的话,如果遇到「e. g.,」或是「(e. g. xxx」的情况就会被跳过。
  2. 英文的句号「.」未转义
  3. 标志位 re.I 不生效

前2个问题好解决。改进代码如下:

1 def punctuate(s):
2 #----其余代码暂略
3 s = re.sub('([^a-zA-Z]e\.) (g\.[^a-zA-Z])', '\g<1>\g<2>', s, re.I)
4 return s

规则是:「e. g.」之前或之后,必须有「非英文字母」的字符(包括空格),且「e.」和「g.」中间有一个空格,则将中间的空格删掉,且保留前后的「非英文字母」(\g<1>表示查找到的第1个括号内的文本,\g<2>表示第2个括号)。但标志位 re.I 的问题还是没解决。

后来翻到了「Python--详解Python中re.sub」这篇文章,才顿悟:re.sub() 函数有5个参数,我传入了4个参数,最后一个被认为是第4个参数,而不是第5个!多么低级的错误啊!

查阅「Python官方文档」可知,

re.sub(pattern, repl, string, count=0, flags=0)

我传入的第4个参数 re.I 会被当作是 count。因此,正确的姿势是明确写明「flags=re.I」。

整个标点符号规范化函数还包括其它的替换,完整代码如下:

 1 def punctuate(s):
2 s = re.sub('([,:;?!\.”\)])', '\g<1> ', s) #后加空格
3 s = re.sub('([“\(])', ' \g<1>', s) #前加空格
4 s = re.sub('([“\(]) ', '\g<1>', s) #后删空格
5 s = re.sub(' ([,:;?!\.”\)])', '\g<1>', s) #前删空格
6 s = re.sub('([,\.?!;\)]) ”', '\g<1>”', s) #闭引号前去空格
7 s = re.sub('\) ([,:;?!\.”])', ')\g<1>', s) #闭括号后去空格
8 s = re.sub('(\d)\. (\d)', '\g<1>.\g<2>', s) #小数点后去空格
9 s = re.sub(' +', ' ', s) #多空格改单空格
10 #拉丁加点缩写单词,点号后面去空格
11 s = re.sub('([^a-zA-Z]e\.) (g\.[^a-zA-Z])', '\g<1>\g<2>', s, flags=re.I)
12 s = re.sub('([^a-zA-Z]i\.) (e\.[^a-zA-Z])', '\g<1>\g<2>', s, flags=re.I)
13 s = re.sub('([^a-zA-Z]q\.) (v\.[^a-zA-Z])', '\g<1>\g<2>', s, flags=re.I)
14 s = re.sub('([^a-zA-Z]v\.) (s\.[^a-zA-Z])', '\g<1>\g<2>', s, flags=re.I)
15 s = re.sub('([^a-zA-Z]n\.) (b\.[^a-zA-Z])', '\g<1>\g<2>', s, flags=re.I)
16 s = re.sub('([^a-zA-Z]p\.) (s\.[^a-zA-Z])', '\g<1>\g<2>', s, flags=re.I)
17 s = re.sub('\. ,', '.,', s)
18 return s

多么痛的领悟!

Python正则表达式 re.sub()函数:标志位flags与参数个数问题的更多相关文章

  1. python学习道路(day4note)(函数,形参实参位置参数匿名参数,匿名函数,高阶函数,镶嵌函数)

    1.函数 2种编程方法 关键词面向对象:华山派 --->> 类----->class面向过程:少林派 -->> 过程--->def 函数式编程:逍遥派 --> ...

  2. 第11.3节 Python正则表达式搜索支持函数search、match、fullmatch、findall、finditer

    一. 概述 re模块的函数search.match.fullmatch.findall.finditer都是用于搜索文本中是否包含指定模式的串,函数的参数都是一样的,第一个参数是模式串.第二个是搜索文 ...

  3. Python中动态编译函数compile(source, filename, mode, ......)参数filename的作用是什么?

    动态编译函数compile调用语法如下: compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) 其中的fi ...

  4. python中,print函数的sep和end参数

    print函数是我们经常使用的,但是它的sep和end参数或许对很多python使用者相对陌生,他们可以让我们的打印更具有个性化. 先来看下官方解释, sep:分割值与值,默认是一个空格 end:附件 ...

  5. js中函数调用时,对参数个数和类型没有要求

    因为js是一种弱类型的编程语言,对数据类型的要求没有其他编程语言的要求严格,所以在定义函数的时候不需要像java一样对其传入参数的类型进行定,也对传入参数的个数没有要求. js函数的参数与大多数其他语 ...

  6. 简介Python正则表达式

    一.概念 简单来说正则表达式是由一些普通字符(例如,a 到 z 之间的字母)和一些元字符组成,用来匹配和过滤一些字符串的一种逻辑公式. 二.正则表达式的一些基本规则 1.一些常用的元字符   ^  : ...

  7. 第11.25节 Python正则表达式编译re.compile及正则对象使用

    一. 引言 在<第11.2节 Python 正则表达式支持函数概览>介绍了re模块的主要函数,在<第11.3节 Python正则表达式搜索支持函数search.match.fullm ...

  8. Python正则表达式处理中的匹配对象是什么?

    老猿才开始学习正则表达式处理时,对于搜索返回的匹配对象这个名词不是很理解,因此在前阶段<第11.3节 Python正则表达式搜索支持函数search.match.fullmatch.findal ...

  9. python正则表达式模块re:正则表达式常用字符、常用可选标志位、group与groups、match、search、sub、split,findall、compile、特殊字符转义

    本文内容: 正则表达式常用字符. 常用可选标志位. group与groups. match. search. sub. split findall. compile 特殊字符转义 一些现实例子 首发时 ...

随机推荐

  1. JavaScript对象原型链的学习

    1.构造函数和原型 1.1对象的三种创建方式 字面量方式 var obj = {}; new关键字 var obj = new Object(); 构造函数方式 function Person(nam ...

  2. OpenSIPS 2.4.2 高并发下,日志丢失怎么办

      问题年年有,今年特别多.最近公司对呼叫中心平台做了大幅度重构,基于OpenSIPS实现的会话管理服务,在高并发压测过程中,发现OpenSIPS的日志居然出现丢失的情况,简直让我食不知味,困惑不已. ...

  3. 攻防世界——Misc新手练习区解题总结<1>(1-4题)

    第一题this_if_flag: 第一题就不多说了,题目上就给出了flag复制粘贴就可以了 第二题pdf: 下载附件后,得到如下界面 Ctrl+a全选文字,复制出来看看是什么,粘贴后恰好得到flag ...

  4. 寻找链表的倒数第k个节点

    寻找链表的倒数第k个节点 题目:已知一个带有表头结点的单链表,节点结构为(data,next),假设该链表只给出了头指针list.在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个 ...

  5. Unity中利用柏林噪声(perlinnoise)制作摇摆效果

    perlinnoise是unity中Mathf下的一个函数,需要两个float参数x和y进行采样,返回一个0-1的float型. 项目里经常要随机摇摆某些东西,比如摄像机,某个随机运动的目标等等,都可 ...

  6. 【Gin-API系列】实现路由分组(七)

    在之前的文章介绍中我们已经完成了一个API服务的全链路请求设计.调用方式可以看Test目录的代码 // src/test/request_test.go func TestAPI_Request(t ...

  7. python学习第八天

    解析库之bs4的基本使用方法 ''' pip install beautifulsoup4#安装bs4 pip install lxml#安装lxml ''' html_doc = "&qu ...

  8. P1164 小A点菜(动态规划背包问题)

    题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家--餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:"随便点". 题目描述 不过ui ...

  9. or2?Scum!(周期性求解)

    链接:https://ac.nowcoder.com/acm/contest/316/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言2621 ...

  10. linux的五种IO模型

    概念: 同步.异步.阻塞.非阻塞的概念 同步:所谓同步,发起一个功能调用的时候,在没有得到结果之前,该调用不返回,也就是必须一件事一件事的做,等前一件做完了,才能做下一件. 提交请求->等待服务 ...