Không có tương đương fscanf
hoặc Java Scanner
. Giải pháp đơn giản nhất là yêu cầu người dùng sử dụng đầu vào phân tách dòng mới thay vì đầu vào được phân tách bằng dấu cách, sau đó bạn có thể đọc từng dòng và chuyển đổi các dòng thành loại chính xác.
Nếu bạn muốn người dùng cung cấp đầu vào có cấu trúc hơn thì có thể bạn nên tạo trình phân tích cú pháp cho đầu vào của người dùng. Có một số thư viện phân tích cú pháp đẹp cho python, ví dụ: pyparsing. Cũng có một mô-đun scanf
, mặc dù bản cập nhật cuối cùng là năm 2008.
Nếu bạn không muốn có phụ thuộc bên ngoài thì bạn có thể sử dụng regexes để khớp với chuỗi đầu vào. Chắc chắn regexes yêu cầu để làm việc trên dây, nhưng bạn có thể dễ dàng vượt qua giới hạn này đọc trong khối. Ví dụ một cái gì đó như thế này nên làm việc tốt hầu hết thời gian:
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ử dụng Ví dụ:
>>> 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
Bạn có lẽ sẽ phải mở rộng này, và thử nghiệm nó đúng nhưng nó sẽ cho bạn một số ý tưởng .
Nếu đầu vào rất bẩn/tùy ý, tôi có xu hướng sử dụng mô đun 're'; nếu đầu vào được cấu trúc, tôi thích một thư viện phân tích cú pháp như simpleparse (EBNL dễ bảo trì hơn các biểu thức thông thường). –
Nếu bạn có một trường hợp sử dụng trong tâm trí, có lẽ nó sẽ có hiệu quả hơn để cập nhật câu hỏi của bạn thay vì thực hiện một yêu cầu chung chung. –
Xem http://stackoverflow.com/questions/2175080/sscanf-in-python để biết một số đề xuất khác. –