Python流提取
2 个回答
1
我所知道的,没有直接对应的东西。不过,你可以用正则表达式做到差不多的效果(可以看看re
模块)。
举个例子:
# matching first integer (space delimited)
re.match(r'\b(\d+)\b',string)
# matching first space delimited word
re.match(r'\b(\w+)\b',string)
# matching a word followed by an integer (space delimited)
re.match(r'\b(\w+)\s+(\d+)\b',string)
这比一般的C语言风格的扫描器接口需要多一点工作,但它也非常灵活和强大。不过,你需要自己处理流输入输出。
3
在Python中,没有像fscanf
或者Java的Scanner
那样的功能。最简单的解决办法是让用户输入以换行符分隔的数据,而不是用空格分隔。这样你就可以逐行读取,然后把每一行转换成正确的数据类型。
如果你希望用户提供更有结构的数据,那你可能需要为用户输入创建一个解析器。Python有一些很不错的解析库,比如pyparsing。还有一个scanf
模块,虽然它最后一次更新是在2008年。
如果你不想依赖外部库,那么你可以使用正则表达式来匹配输入的内容。正则表达式确实需要在字符串上工作,但你可以通过分块读取来轻松解决这个问题。比如,下面的代码通常能很好地工作:
import re
FORMATS_TYPES = {
'd': int,
'f': float,
's': str,
}
FORMATS_REGEXES = {
'd': re.compile(r'(?:\s|\b)*([+-]?\d+)(?:\s|\b)*'),
'f': re.compile(r'(?:\s|\b)*([+-]?\d+\.?\d*)(?:\s|\b)*'),
's': re.compile(r'\b(\w+)\b'),
}
FORMAT_FIELD_REGEX = re.compile(r'%(s|d|f)')
def scan_input(format_string, stream, max_size=float('+inf'), chunk_size=1024):
"""Scan an input stream and retrieve formatted input."""
chunk = ''
format_fields = format_string.split()[::-1]
while format_fields:
fields = FORMAT_FIELD_REGEX.findall(format_fields.pop())
if not chunk:
chunk = _get_chunk(stream, chunk_size)
for field in fields:
field_regex = FORMATS_REGEXES[field]
match = field_regex.search(chunk)
length_before = len(chunk)
while match is None or match.end() >= len(chunk):
chunk += _get_chunk(stream, chunk_size)
if not chunk or length_before == len(chunk):
if match is None:
raise ValueError('Missing fields.')
break
text = match.group(1)
yield FORMATS_TYPES[field](text)
chunk = chunk[match.end():]
def _get_chunk(stream, chunk_size):
try:
return stream.read(chunk_size)
except EOFError:
return ''
示例用法:
>>> s = StringIO('1234 Hello World -13.48 -678 12.45')
>>> for data in scan_input('%d %s %s %f %d %f', s): print repr(data)
...
1234
'Hello'
'World'
-13.48
-678
12.45
你可能需要对这个进行扩展,并进行适当的测试,但这应该能给你一些思路。