在Python中使用split()和join()时保留空白符

37 投票
3 回答
27594 浏览
提问于 2025-04-17 20:01

我有一个数据文件,里面有一些列,像这样:

BBP1   0.000000  -0.150000    2.033000  0.00 -0.150   1.77

而且这些列之间用不同数量的空格分隔。

我的目标是读取这些行,对几行进行一些数学运算,比如把第4列的值乘以0.95,然后把结果写入一个新文件。新文件的格式应该和原来的文件一样,只是我修改过的值会有所不同。

我打算把这些行作为列表中的项来读取。然后我会对我感兴趣的那些行使用 split(),这样就能得到一个包含各个列值的子列表。接着我进行修改,再用 join() 把这些列连接起来,最后把列表中的行写入一个新的文本文件。

问题是,我有不同数量的空格。我不知道怎么把这些空格以我读取时的方式重新放回去。我能想到的唯一方法是先在分割之前计算行中的字符数,但这会非常麻烦。有没有人有更好的办法来解决这个问题?

3 个回答

4

对于那些开头和/或结尾有空格的行,使用一个更强大的模式 (\S+) 来根据非空格字符进行分割会更好:

import re

line1 = ' 4   426.2   orange\n'
line2 = '12    82.1   apple\n'

re_S = re.compile(r'(\S+)')
items1 = re_S.split(line1)
items2 = re_S.split(line2)
print(items1)  # [' ', '4', '   ', '426.2', '   ', 'orange', '\n']
print(items2)  # ['', '12', '    ', '82.1', '   ', 'apple', '\n']

这两行在分割后得到的项目数量是一样的,这样很方便。第一项和最后一项总是空格字符串。我们可以用一个空字符串来把这些行重新组合起来:

print(repr(''.join(items1)))  # ' 4   426.2   orange\n'
print(repr(''.join(items2)))  # '12    82.1   apple\n'

为了和这里其他答案中使用的类似模式 (\s+)(小写)进行对比,每一行分割后的结果长度和项目位置都不一样:

re_s = re.compile(r'(\s+)')
print(re_s.split(line1))  # ['', ' ', '4', '    ', '20.0', '   ', 'orange', '\n', '']
print(re_s.split(line2))  # ['12', '    ', '82.1', '   ', 'apple', '\n', '']

如你所见,这样处理起来会稍微复杂一些,难以保持一致。

9

还有一种方法可以做到这一点:

s = 'BBP1   0.000000  -0.150000    2.033000  0.00 -0.150   1.77'
s.split(' ')
>>> ['BBP1', '', '', '0.000000', '', '-0.150000', '', '', '', '2.033000', '', '0.00', '-0.150', '', '', '1.77']

如果我们在分割函数中指定空格作为参数,它会创建一个列表,而不会把连续的空格都去掉。所以,在使用'连接'函数之后,原来的空格数量会被恢复。

45

在这种情况下,你可以使用 re.split(),并且要用到一个分组:

re.split(r'(\s+)', line)

这样做会同时返回列和空格,这样你就可以在后面把这一行重新组合起来,保持原来的空格数量。

举个例子:

>>> re.split(r'(\s+)', line)
['BBP1', '   ', '0.000000', '  ', '-0.150000', '    ', '2.033000', '  ', '0.00', ' ', '-0.150', '   ', '1.77']

你可能确实想把最后的换行符去掉。

撰写回答