基于多个分隔符拆分字符串不能得到一致的结果

3

我有一个包含许多行信息的文件类型,如下所示:

  P087 = ( 4.000000000000000E+001,-6.250000000000000E-001 )
  P088 = ( 4.000000000000000E+001, 0.000000000000000E+000 )

我正在逐行读取此文件,使用

fo = open(FileName, 'r')
for line in fo:
    #do stuff to line

我想知道如何将每行拆分为以下列表:
[87, 40.0,-0.625]
[88, 40.0, 0.0]

我尝试使用Python的正则 .split() 方法进行分割,但它不能一致地将行分割,导致每行的列表长度不同。

我还尝试了使用re.split()和类似于re.split([ = ( ]|,)的东西,但都没有起作用。我也不太常使用正则表达式(虽然我知道它们非常强大),这就解释了我为什么很难找到正确的方法。

我想我需要用' = ( '','来定界行,但我真的不确定如何做才能使得结果列表是一致的。非常感谢任何帮助。

谢谢!


你的意思是每一行都像这个字符串: 'P087 = ( 4.000000000000000E+001,-6.250000000000000E-001 )'吗? - user7986928
是的,正是我想表达的意思。 - user32882
你能否使用正则表达式匹配整个字符串,并使用一些捕获组来获取你想要的值?(请参阅https://docs.python.org/2/howto/regex.html#grouping) - Jay
尝试对每行使用[^ (),=P\r\n]+进行查找。 - user557597
6个回答

4

使用ast.literal_eval()解析元组字符串:

import ast
import re

with open(FileName, 'r') as f:
    out = [
        [int(re.findall('(?<=P)\d+', k)[0]), *ast.literal_eval(v.strip())]
        for k, v in [line.split('=') for line in f]
    ]

2
这应该可以解决问题:
for line in fo:
    parts = re.match(r'\s*P(\d+)\s*=\s*[(]\s*([^ ,]*)[ ,]+([^ ,]*)[ )]*',line).groups()
    print([int(parts[0]), float(parts[1]), float(parts[2])])

re.match 用于提取重要部分,然后将每个部分解析为适当的类型以便打印。


运作得很好。您是否有其他匹配字符串,例如 SE104 = ( P1555, P1378, P1379, P1380, P1377, P1363, P1362, P1361, P1367, P1371, P1372, P1373, P1364, P1365, P1366 ) 转换为 [104, 1555, 1378, 1378 ....]?在这种情况下,所有的都是整数。 - user32882
还有,([^ ,]*) 这部分是什么意思?你在这里使用插入符号作为否定符号吗?也就是说,将任何不是逗号的内容分组? - user32882
([^ ,]*) 会匹配除了空格或逗号以外的字符序列。 - Scott Hunter

2

一种无需使用正则表达式的解决方案:

def parse_line(line):
    first, second = line.split(',')
    ind = int(first.split()[0][2:])
    num1 = float(first.split()[-1])
    num2 = float(second.split()[0])
    return [ind, num1, num2]

line = 'P087 = ( 4.000000000000000E+001,-6.250000000000000E-001 )'
print(parse_line(line))

line = ' P088 = ( 4.000000000000000E+001, 0.000000000000000E+000 )'
print(parse_line(line))

1
下面的正则表达式将从您的文件中提取所有行:
c = re.compile(r'\s*P(\d+)\s*=\s*\(\s*([\d\.\+\-E]+)\s*,\s*([\d\.\+\-E]+)\s*\)')
lines = list(c.findall(x))

其中x是你的文件内容字符串。


1

并不总是一个好主意,但在以下情况下eval可能是理想的选择:

from ast import literal_eval
result = []
for line in fo:
  item = []
  name, val = line.split('=')
  item.append(name.strip())
  item.extend(literal_eval(val.strip()))
  result.append(item)

print(result)

0

正则表达式[-0-9.]+[-E+0-9]*[-\d.]+[-E+\d]*

细节:

  • [] 匹配列表中的单个字符
  • + 匹配一次无限次
  • * 匹配零次无限次

Python 代码

import re

def arr_num(text):
    array = []
    for n in re.finditer(r'[-0-9.]+[-E+0-9]*', text):
        array.append(n.group().isdigit() and int(n.group()) or float(n.group()))
    return array

输出:

arr_num("SE104 = ( P1555, P1378, P1379, P1380, P1377, P1363, P1362, P1361, P1367, P1371, P1372, P1373, P1364, P1365, P1366 )")
>>> [104, 1555, 1378, 1379, 1380, 1377, 1363, 1362, 1361, 1367, 1371, 1372, 1373, 1364, 1365, 1366]

arr_num("P087 = ( 4.000000000000000E+001,-6.250000000000000E-001 )")
>>> [87, 40.0, -0.625]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接