由于工作需要,最近再一次学习python,很多人看来,我一个写嵌入式C的码农来鼓捣python,估计不是很理解,可能还会有鄙视的。不管怎么说,一切还是工作需要。
目前用已经用C和Java分别开发了几个PC端的命令行程序,作为基础工具,通过它们之间的相互调用来协调完成一些自动化工作,这其中还涉及到很多字符处理,逻辑判断和参数传递问题,这就得再设计一套上层逻辑控制程序来实现业务需求,虽然windows的批处理应该也可以实现,但是被称为“胶水语言”的python风头正火,何不蹭点流量呢?
进入正题, 有字符串如下,我们需要用python提取字符串中的文件路径(不要问我为什么还是这么千篇一律的需求,就是这么简单),实际应用中会有中文路径或者文件名带中文,空格。
"other F:\\cc89.bmp F:\\cc890.bmp other"
直接上正则表达式:
# 原字符
test_str = "other F:\\cc89.bmp F:\\cc890.bmp other"
# match()方法从字符串的第一个字符开始匹配,若第一字符匹配则继续,成功则返回匹配对象,否则返回None
m = re.match(r'[A-Z]:.+.bmp', test_str)
if m is not None:
print(m.group())
else:
print("Not match anything")
# 表达是说明:[A-Z]字符串以A-Z中任意一个字符开始,后面的:一起就构成了盘符如F:, .+任意字符任意次
# 匹配路径和文件名部分, .bmp就是字面值.bmp,指定文件后缀
# 此方法运行后并没有成功匹配任何字符串,因为match从字符串第一个字符开始,而
# search()方法会从头开发搜索整个字符串,直到发现与模式匹配的字串或者字符结束才会停止
输出结果:
Not match anything
再来:
m = re.search(r'[A-Z]:.+\.bmp', test_str)
if m is not None:
print(m.group())
else:
print("Not match anything")
# 表达式解析:与match样, 不同的是, search从字符串第一个字符开始向后搜索,直到发现匹配项或者字符
# 结束才会停止
输出:
F:\cc89.bmp F:\cc890.bmp
从无到有,不错,再来:
# 可以看出match()与search()的还是有区别的
# 然而search()的输出结果为 F:\cc89.bmp F:\cc890.bmp,也就是两个文件名都被识别出来了,可以仔细分析
# 一下,表达式的逻辑是没有问题的, 那么问题在于匹配到第一个目标之后,是否需要继续匹配后续的字符
# 这就涉及到正则表达式的“贪婪”模式,默认情况下.+匹配所有符合的字符, 这就把第一个文件路径全部包含了
# 以至于两个文件路径被匹配成一个结果。这也没什么问题,但是如果我们只需要第一个文件名呢?
# 这就需要使用非贪婪模式, 即 .+尽可能少的匹配,而剩余的部分考虑用后面的模式项去处理, 例子中就是\.bmp
# \.是把.转义为字面值.,构成.bmp文件后缀, 这样当.bmp匹配了之后,由于后面剩余的字符就没有模式去匹配,整个
# 匹配过程到此结束。 非"贪婪"模式用?来修饰数量词 "*","+","?","{m,n}
m = re.search(r'[A-Z]:.+?\.bmp', test_str)
if m is not None:
print(m.group())
else:
print("Not match anything")
输出:
F:\cc89.bmp
嗯嗯,差不多了,再进一步,扩展一下:
# findall()方法则会从头开始搜索整个字串,把所有匹配的部分都找出来,结果作为list返回
# 与search()方法类似, 但结束条件不同, search()只会匹配第一个,成功之后即停止,而findall会搜索整个
# 字符串,所有匹配项都会输出
m = re.findall(r'[A-Z]:.*?\.bmp', test_str)
if len(m) > 0:
print(m)
else:
print("Not match anything")
# 同样,如果findall的模式项变成贪婪版本之后,两个文件名会被一个模式匹配出来
m = re.findall(r'[A-Z]:.*\.bmp', test_str)
if len(m) > 0:
print(m)
else:
print("Not match anything")
输出:
['F:\\cc89.bmp', 'F:\\cc890.bmp']
['F:\\cc89.bmp F:\\cc890.bmp']
#说明,findall的输出结果是一个列表,即使是空列表。注意观察上面两个findall的结果,第一个非贪婪版本的list有两个元素,而第二个只有一个元素,两个文件名被一个模式完全匹配出来了。
结果与理论一致,OK核心功能验证完成,准备收工了。
为什么不是C?
其实也尝试过用我的主力语言C来实现,首先sscanf,fscanf,strstr等字符串格式相关函数都用过,不过特别费心费力,开发效率非常低,而且扩展性不好。除了主力语言,作为第二第三语言,Python绝对是一个不错的选择。