Python中的sscanf
我在找一个和 sscanf()
在 Python 中类似的东西。我想解析 /proc/net/*
文件,在 C 语言中我可以这样做:
int matches = sscanf(
buffer,
"%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n",
local_addr, &local_port, rem_addr, &rem_port, &inode);
我一开始想用 str.split
,但是它并不是根据给定的字符来分割,而是把 sep
整个当作一个字符串来处理:
>>> lines = open("/proc/net/dev").readlines()
>>> for l in lines[2:]:
>>> cols = l.split(string.whitespace + ":")
>>> print len(cols)
1
根据上面的解释,这应该返回 17。
有没有和 sscanf
类似的 Python 方法(不是正则表达式),或者在标准库中有没有可以根据一系列字符进行分割的字符串分割函数,我不知道的?
9 个回答
75
当我想用C语言风格编程的时候,我通常会用zip和列表推导式来实现类似scanf的功能。就像这样:
input = '1 3.0 false hello'
(a, b, c, d) = [t(s) for t,s in zip((int,float,strtobool,str),input.split())]
print (a, b, c, d)
需要注意的是,对于更复杂的格式字符串,你需要使用正则表达式:
import re
input = '1:3.0 false,hello'
(a, b, c, d) = [t(s) for t,s in zip((int,float,strtobool,str),re.search('^(\d+):([\d.]+) (\w+),(\w+)$',input).groups())]
print (a, b, c, d)
另外,你还需要为所有想要转换的类型准备转换函数。例如,上面我用了类似这样的:
strtobool = lambda s: {'true': True, 'false': False}[s]
100
还有一个叫做 parse
的模块。
parse()
的设计目的是与 format()
相反,后者是 Python 2.6 及更高版本中的一种新的字符串格式化函数。
>>> from parse import parse
>>> parse('{} fish', '1')
>>> parse('{} fish', '1 fish')
<Result ('1',) {}>
>>> parse('{} fish', '2 fish')
<Result ('2',) {}>
>>> parse('{} fish', 'red fish')
<Result ('red',) {}>
>>> parse('{} fish', 'blue fish')
<Result ('blue',) {}>
38
Python没有像sscanf
这样的内置功能,其实大多数情况下,直接处理字符串、使用正则表达式或者解析工具来解析输入会更合理。
这个sscanf
功能可能主要是为了方便把C语言的代码转换过来,所以有人实现了这个功能,比如在这个模块里:http://hkn.eecs.berkeley.edu/~dyoo/python/scanf/
如果你只是想根据多个分隔符来拆分数据,re.split
真的是最合适的工具。