继续 PythonCookbook, 感觉我这波取名怪怪的, 字符串文本, 本质上其实一回事情. 哦, 恰好, 最近一个小伙伴说要转行数据这块, 再跟我探讨经验, 毕竟我是这样过来的. 嗯... 其实我特别害怕回答这个问题, 鼓励也不是, 不鼓励也不是. 从亲历来看, 确实不太容易, 要学的东西真的太多了, 只是稍微客观说了一下.
决定了,就要做好准备,转行其实,不太容易,尤其是专业技术这块,不可能速成,需要时间的积累.
然后关于学习方法啥的, 哪有什么技巧, 又不是大学考试, 临时突击... 这没有捷径的, 哪有速成, 只是, 付出的时间和精力太多了, 才慢慢有所领悟
故余虽愚, 卒获有所闻.
当然最后, 我也是说了下, 我所谓的方法, 其实就是花时间, 没有别的, 代码这块, 见多识广, 唯手熟尔.
我当时学的时候,比较蠢,就抄别人的代码,一股脑儿的抄,,,每天坚持抄,直到现在也是,抄的量比较大了,比如一年几万行,就慢慢理解了,自己就会写了.
当然,我现在也不怎么写了,主要是之前收藏了很多,抄抄改改就行了.
职业, 人生问题, 不必探讨; 技术细节,欢迎交流
扯远了, 回归正题, 关于字符串匹配, 搜索方面的小 tips.
字符串匹配和搜索
需求
对字符串进行搜索或匹配搜索, 依据特定模式.
方案
简单的用内置方法如 starswith(); endswith(); find(); rfind() 这些, 复杂的用 re 正则表达式, 能解决一切匹配问题.
text = "yeah, but no, but yeah, but no, but yeah"
# Exact math
text == 'yeah'
False
print(text.startswith('yeah'))
print(text.endswith('no'))
print(text.find('no'))
True
False
10
对于稍微复杂一些的就要用到正则表达式了. 比如这里我们先来匹配日期字符串如 05/20/2020 可以这样写.
import re
text_01 = "05/20/2020"
text_02 = "may,22,2020"
# "d" 匹配数字; "+" 表示最少一次
if re.match(r"d+/d+/d+", text_01):
print('yes')
else:
print('no')
print('yes') if re.match("d+/d+/d+", text_02) else print("no")
yes
no
re.match() 匹配到, 返回的是是一个对象, 用 group() 方法可拿出了; 若无匹配到, 则返回 None. 而不直接报错, 鲁棒性还是可以的哦.
re.match(r"d+/d+/d+", text_01).group()
'05/20/2020'
re.comple() 用于, 同一个模式, 做多次匹配的场景, 因为, 不可能重复写多次吧.
# re.compile() 用于多次重复匹配的情况
date_pat = re.compile(r"d+/d+/d+")
print('yes') if date_pat.match(text_01) else print('no')
print('yes') if date_pat.match(text_02) else print('no')
yes
no
re.findall() 返回匹配成功的对象(任意位置), 以列表形式. 是我最常用的了. 与 re.match() 不同在于, match() 只是从字符串头部开始匹配, 一旦匹到就不再继续了.
text = "Today is 05/20/2020. My first Python Programming starts 4/20/2015"
print(date_pat.findall(text))
['05/20/2020', '4/20/2015']
通常还会利用括号去捕获分组. 分组的好处是可以让后面的处理更加简单, 分组提取了嘛.
date_pat = re.compile(r"(d+)/(d+)/(d+)")
ret = date_pat.match("05/20/2020")
print(ret)
print(ret.group(0))
print(ret.group(1))
print(ret.group(2))
print(ret.group(3))
print(ret.groups())
print(date_pat.findall(text))
# 拆包
for month, day, year in date_pat.findall(text):
print(f"{year}-{month}-{day}")
<_sre.SRE_Match object; span=(0, 10), match='05/20/2020'>
05/20/2020
05
20
2020
('05', '20', '2020')
[('05', '20', '2020'), ('4', '20', '2015')]
2020-05-20
2015-4-
re.findall( ) 方法会搜索文本并以列表方式返回, 于是呢, 如果想用迭代的方式返回, 则用 re.finditer() 即可.
for m in date_pat.finditer(text):
print(m.groups())
('05', '20', '2020')
('4', '20', '2015')
注意一点是, re.match() 方法, 仅仅是检查字符串开始的部分, 对于结尾并没有限定, 如果是想要更加精确, 则 用 '$'
date_pat = re.compile(r"(d+)/(d+)/(d+)$")
字符串搜索替换
需求
在字符串中, 对指定的文本进行搜索和替换
方案
同样对于简单的模式, 直接用 str.replace( ) 即可. 复杂的用 re.sub( )
text = "yeah, but no, but yeah, but no, but yeah"
text.replace('yeah', '520')
'520, but no, but 520, but no, but 520'
re.sub (pattern, repl, string,...) 有3个重要的参数, 第一个是匹配模式, 第二个是用来替换的 字符串; 第三个是目标字符串.
import re
text = "Today is 05/20/2020. My first Python Programming starts 4/20/2015"
re.sub(r"(d+)/(d+)/(d+)", "520", text)
'Today is 520. My first Python Programming starts 520'
小结
- 字符串查找替换, 优先考虑内置方法, 如 startswith(), endswith(), replace() ...
- 复杂的用正则, re.math(); re.findall(); re.sub(); re.compile( ) , 分组 group 等非常常用的
- 最后就是字符串正则...特别灵活和重要且强大, 必须要会编写哦.