python - 使用 Python splitlines() 将文本文件转换为列表,同时还将一些行组合成列表中的单个项目
问题描述
我正在努力将原本打算与 VBA 应用程序一起使用的文本文件转换为新 Python 应用程序的字符串列表。每个文本文件在带有多个字符串的单独行上都有“向量”,但为了简单起见,我只是给每个文件一个字符串。我遇到的问题是,由于 Excel/VBA 的行字符限制,向量占用多行。这是一个例子:
vector(1)="这是第一个只占一行的向量!"
vector(2)="这是向量 2 的一些文本,但它还在继续!"
vector(2)= vector(2) & "这是向量 2 文本的延续!"
vector(3)= "这是一个只有一行的新向量!"
我试图做的是遍历由 splitlines() 创建的列表以创建一个新列表,该列表通过尝试回顾上一行以查看它是否具有相同的“vector(x)”标签然后加入附加到我的最终列表之前的字符串。但是,它随后会将未完成的字符串和连接的字符串添加到列表中。这是我正在使用的代码:
import os
import re
Lines = open(doc).read().splitlines()
New_Lines = []
previous_label = 0
vector_label = 0
previous_contents = 0
vector_contents = 0
for z, vector_check in enumerate(Lines, 1):
if vector_check.startswith("vector"):
v_split = re.split(r"=", vector_check)
previous_label = vector_label
vector_label = v_split[0]
previous_contents = vector_contents
vector_contents = v_split[1]
else :
continue
# print(vector_label)
if previous_label != vector_label:
repeat = 0
New_Lines.append(vector_contents)
else :
repeat += 1
vec_split_2 = re.split(r"&", v_split[1])
vector_contents = previous_contents[:-1] + " " + vec_split_2[1][2:]
New_Lines.append(vector_contents)
print(vector_contents)
continue
i = 1
for obj in New_Lines:
print("vector_CRS(" + str(i) + ")=" + obj)
i += 1
给出结果:
vector_CRS(1)="这是第一个只占一行的向量!"
vector_CRS(2)="这是向量 2 的一些文本,但它还在继续!"
"vector_CRS(3)="这是向量 2 的一些文本,但它还在继续!这是向量 2 文本的延续!"
"vector_CRS(4)= "这是一个只有一行的新向量!"
我也尝试在列表中向前看(这就是枚举存在的原因),但结果比这些更糟糕。这是整个较大脚本的“难题”的最后一块,尽管感觉很简单,就像我错过了一个简单的答案,但我花了几个小时试图修复这部分。
解决方案
如果你有一个文本文件vectors.txt
,它看起来像这样:
vector(1)="This is the first vector that only takes 1 line!"
vector(2)="This is some of the text for vector 2 but it continues!"
vector(2)= vector(2) & "This is the continuation of the text for vector 2!"
vector(3)= "This is a new vector with only a single line!"
您可以使用itertools.groupby
正则表达式模式按它们的编号对向量进行分组。然后,使用另一个正则表达式,合并组中每个向量的所有内容:
def main():
with open("vectors.txt", "r") as file:
lines = file.read().splitlines()
def merge_vectors(lines):
from itertools import groupby
import re
for _, group in groupby(lines, key=lambda line: re.match(r"vector\((\d+)\)", line).group(1)):
yield " ".join(re.search("\"(.+)\"", item).group(1) for item in group)
print(list(merge_vectors(lines)))
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
输出:
['This is the first vector that only takes 1 line!', 'This is some of the text for vector 2 but it continues! This is the continuation of the text for vector 2!', 'This is a new vector with only a single line!']
>>>
这假定vectors.txt
文件中的行已经按向量编号分组在一起。例如,它假定您不能拥有以下内容:
vector(1)="Part of one"
vector(2)="Part of two"
vector(1)= vector(1) & "Also part of one"
编辑 - 我查看了您的repl.it
. 我对正则表达式模式和一般代码进行了一些更改——我只是更明确地做了几个步骤。现在的模式更宽松了,例如类似的东西vector(2)= vector(2) & ""
将不再抛出异常,但由于双引号之间没有内容,它将被忽略。不以双引号结尾的行也会被处理。所有行在处理之前也会被过滤,以便只包含以开头的行vector_CRS(...)
,因此您不再需要手动跳过前五行左右。
def main():
import re
line_pattern = r"vector_CRS\((?P<vector_number>\d+)\)"
content_pattern = "\"(?P<content>.*)\"?"
def is_vector_line(line):
return re.match(line_pattern, line) is not None
with open("vectors.txt", "r") as file:
lines = list(map(str.strip, filter(is_vector_line, file)))
def merge_vectors(lines):
from itertools import groupby
def key(line):
return re.match(line_pattern, line).group("vector_number")
def get_content(item):
return re.search(content_pattern, item).group("content")
for _, group in groupby(lines, key=key):
yield " ".join(filter(None, map(get_content, group)))
merged = list(merge_vectors(lines))
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
推荐阅读
- flash - Flash 8 key.isDown 代码
- javascript - 如何更改待办事项列表中未来元素的 css?
- bash - 如何从文件中递归删除文件扩展名?
- python - 在以前工作的系统上遇到“无法创建 cudnn 句柄:CUDNN_STATUS_NOT_INITIALIZED”
- sql - 如何从 INFORMATION_SCHEMA.COLUMNS 和 CROSS APPLY TABLE 中 UNION/LEFT JOIN/INNER JOIN 结果?
- python - 有没有办法使用 Python 从 JSON 文件中删除某些字符串?
- python - 从 Python 中的列表理解构造键:值对
- python - 在 python 空闲时处理多个文件
- python - 重塑的输入与理想不同[重塑的输入是具有 x 值的张量,但需要 y 值]
- node.js - 如果不创建另一个事件侦听器,则检查是否调用事件