使用ython读取文本文件中没有空格的数字

时间:2015-12-02 16:37:08

标签: python

我是Python的新手,很难读取这样的文本文件:

  0.42617E-03-0.19725E+09-0.21139E+09 0.37077E+08
  0.85234E-03-0.18031E+09-0.18340E+09 0.28237E+08
  0.12785E-02-0.16583E+09-0.15887E+09 0.20637E+08

因此文件中的数字之间没有逗号或空格分隔符。 使用Matlab我知道如何指定格式,但如何在Python中执行?

我一直在尝试np.loadtxt,但不知道如何设置要读取的位数,所以如果有人能给我一个提示,我会非常感激。

提前致谢, 埃里克

3 个答案:

答案 0 :(得分:2)

为了扩展我的评论,基于您可以使用MATLAB成功解析它的事实,我假设这些字段是固定宽度。在这种情况下,您可以根据字段宽度对每一行进行切片,然后将其转换为numpy数组(如果您需要的话)。举个例子:

import numpy

input_data = """ 0.42617E-03-0.19725E+09-0.21139E+09 0.37077E+08
 0.85234E-03-0.18031E+09-0.18340E+09 0.28237E+08
 0.12785E-02-0.16583E+09-0.15887E+09 0.20637E+08
"""
input_rows = input_data.split('\n')

width = 12
num_fields = 4

data = []
for input_row in input_rows:
    if not input_row:
        continue
    data.append([float(input_row[width * i:width * (i + 1)].strip()) for i in range(num_fields)])

data = numpy.array(data)
print(data)

输出:

[[  4.26170000e-04  -1.97250000e+08  -2.11390000e+08   3.70770000e+07]
 [  8.52340000e-04  -1.80310000e+08  -1.83400000e+08   2.82370000e+07]
 [  1.27850000e-03  -1.65830000e+08  -1.58870000e+08   2.06370000e+07]]

当然,这个例子使用一个固定的字符串来表示输入数据,但你可以想象用你的输入流做类似的事情。

答案 1 :(得分:1)

其他答案使用的方法依赖于数字具有相同宽度的事实或使用科学方法。在这里,我提出了一种接受浮点数(固定宽度或不固定宽度)的方法。

如果要处理C中的给定输入,则可能会使用scanfsscanf。 Python具有与printf类似的功能(例如字符串的format方法),但是没有scanfsscanf之类的功能。

幸运的是,您可以在Python标准库中使用ctypes直接使用sscanf函数。以下示例适用于Linux系统上的Python:

import ctypes
libc = ctypes.CDLL("libc.so.6")
sscanf = libc.sscanf
with open("test") as fp:
    for l in fp:
        float_1 = ctypes.c_float()
        float_2 = ctypes.c_float()
        float_3 = ctypes.c_float()
        float_4 = ctypes.c_float()
        sscanf(ctypes.create_string_buffer(bytes(l,"utf8")), b"%f%f%f%f", ctypes.byref(float_1), ctypes.byref(float_2),ctypes.byref(float_3),ctypes.byref(float_4))
       # You can check the return va Lue of sscanf for errors. It should return 1 when every
        print(float_1.value, float_2.value, float_3.value, float_4.value)

输出为

0.00042617000872269273 -197250000.0 -211390000.0 37077000.0
0.0008523400174453855 -180310000.0 -183400000.0 28237000.0
0.0012784999562427402 -165830000.0 -158870000.0 20637000.0

在(不太可能)您的系统不使用glibc或使用旧版本的情况下,请相应地更改库的路径。 (您的系统很可能没有C库,也不太可能没有实现scanf)如果使用Windows,请将libc = ctypes.CDLL("libc.so.6")更改为

libc = ctypes.cdll.msvcrt # Loads MS standard C Library

ctypes仅使用标准调用约定在动态库中调用函数。您可以使用它来将Python代码与几乎所有C库连接起来

如果您不想使用ctypes,则可以使用某些社区库,例如scanfparse,两者都实现了scanf的功能。 / p>

答案 2 :(得分:0)

你可以滥用这样一个事实,即数字看起来都是科学记数法,并使用正则表达式将每个数字拉出来。

import re

e_numbers = re.compile(r"[\d.]*?E[+-]\d{2}")

with open('yourfile.txt') as f:
    numbers = [float(num) for lst in [e_numbers.findall(line) for line in f] for num in lst]

将该正则表达式拉出来:

e_numbers = re.compile(r'''
    [\d.]*?             # zero or more of the following:
                        #   0123456789.
                        # matching the fewest possible
    E                   # the literal letter 'E'
    [+-]                # either a literal '+' or a literal '-'
    \d{2}               # followed by two digits 0-9''', re.X)