文本-多行匹配和非贪婪 (03)

什么 520 , 跟我有什么关系? 单身狗不配过节, 只有默默地加班, 还有腾出点时间来, 练习一些基础代码来维持手感. 毕竟代码这块, 一直要保持良好的手感和时刻准备着, 嗯... 唯手熟尔. 希望, 下个520 , 能找个对象, 虽然看上去有点困难, 但, 万一实现了呢?

但毕竟, 这也是一个毕竟特殊的日期嘛, 2020-5-20. 虽然我一个人, 但, 浪漫还是要有的呀, 起码画个心来表示一下, 代码网上随便抄的哈, 不要在乎这些细节.

import matplotlib.pyplot as plt 
import numpy as np  
import math   


t = np.linspace(0, math.pi, 1000) 
x = np.sin(t) 
y = np.cos(t) + np.power(x, 2.0 / 3) 


plt.scatter(x,y,c=y,cmap=plt.cm.Reds,edgecolor='none', s=40)
plt.scatter(-x,y,c=y,cmap=plt.cm.Reds,edgecolor='none', s=40)
plt.axis([-2,2,-2,2])

plt.xlabel('Hi~ i am youge, nice to meet you~', fontsize=14)  
plt.ylabel('2020-05-20',fontsize=14)
plt.title("dy / (I love you) = 0 ",fontsize=30)
plt.show()

兄弟们, 这虽然成本低, 朴实无华, 但, 这难到不更加浪漫吗?

兄弟a: 代码报错了.
兄弟b: "i love you " 是一个常量
我想说: "人生若只如初见" -> "我心永恒"
...
兄弟a: 代码通常从右往左看...这尼玛, 渣男. 
我想说: 还是跟IT的兄弟们, 沟通快乐得一批 !

文本非贪婪匹配

需求

基于某个文本匹配模式, 修改其匹配最短符合条件的文本, 即非贪婪匹配.

方案

Python 中的正则支持, 是贪婪匹配的, 即尽可能地多匹配数据, 像其他语言可能是不一样的, 好像 js 就是非贪婪的, 我有点忘了. 但有的时候呢, 我们需要尽可能少匹配, 目的就是为了灵活地满足自身需求.

通常, 该问题一般出现在需要匹配一对 分隔符 之间的文本的时候, 比如引号包含的字符:

# 匹配被双引号 " xxx" 包围的文本 '\' 是转义双引号的
str_pat = re.compile(r'\"(.*)\"')
text1 = 'Computer says "no. "'

print(str_pat.findall(text1))

text2 = 'Computer says "no." Phone says "yes."'
print(str_pat.findall(text2))
['no. ']
['no." Phone says "yes.']

可以从 text2 的匹配结果中看出, Python 默认是贪婪的, 也不能严格这样说, 跟正则表达式自身也有关系.

在正则中, " * " 操作符是贪婪的, 匹配任意个字符(>=0) . 如果要对其进行限制, 比如只匹配一次, 则用 问号 "?" 来进行限定修饰即可.

# 尽可能少匹配, "xxx" 里面的内容
str_pat = re.compile(r'\"(.*?)\"')
# text2 中有2处匹配的地方, 每处尽可能少匹配
print(str_pat.findall(text2))
['no.', 'yes.']

正则表达式的灵活使用,就基本语法层, 比如 * . ? {n} 分组, 转义 .... 等的基本操作, 是必须要熟练的, 因为, 真的太强大的呀. 也是我最为推崇备至的技术之一.

文本多行匹配

需求

用正则匹配的时候, 需要跨行去进行多行匹配

方案

这个问题, 当在使用 (.) 去匹配任意字符的时候, 就会突然忘了 (.) 不能匹配换行符的事实.

# 匹配注释 /* 这是注释 */ , \* 表示对 * 进行转义
comment = re.compile(r'/\*(.*?)\*/')

text1 =  '/* this is a comment */' 
text2 =  '''
            /* this is a 
             multiline comment */ ...
             
             ''' 
print(comment.findall(text1))
print(comment.findall(text2))
[' this is a comment ']
[]

可以看到, 对于有换行符的, 跨行匹配就需要特殊处理一下哦, 用非捕获组 (?:.}\n) 这样的形式来限定.

# 跨行匹配, 设置一个不捕获 \n 的修饰
comment = re.compile(r'/\*((?:.|\n)*?)\*/') 
print(comment.findall(text2))
[' this is a \n             multiline comment ']
posted @ 2020-05-20 23:59  致于数据科学家的小陈  阅读(202)  评论(0编辑  收藏  举报