Python 从文本文件中提取两行之间的数据

Python 从文本文件中提取两行之间的数据,python,algorithm,logic,extract,text-extraction,Python,Algorithm,Logic,Extract,Text Extraction,假设我有数百个文本文件,如以下示例所示: NAME John Doe DATE OF BIRTH 1992-02-16 BIO THIS is a PRETTY long sentence without ANY structure HOBBIES //..etc.. 姓名、出生日期、个人简历和爱好(以及其他)总是存在,但文本内容和它们之间的行数有时会发生变化 我希望遍历该文件并在每个键之间存储字符串。例如,变量名应该包含存储在“Name”和“dateofbirth”之

假设我有数百个文本文件,如以下示例所示:

NAME
John Doe

DATE OF BIRTH

1992-02-16

BIO 

THIS is
 a PRETTY
 long sentence

 without ANY structure 

HOBBIES 
//..etc..
姓名、出生日期、个人简历和爱好(以及其他)总是存在,但文本内容和它们之间的行数有时会发生变化

我希望遍历该文件并在每个键之间存储字符串。例如,变量名应该包含存储在“Name”和“dateofbirth”之间的值

这就是我发现的:

lines = f.readlines()
for line_number, line in enumerate(lines):
    if "NAME" in line:     
        name = lines[line_number + 1]  # In all files, Name is one line long.
    elif "DATE OF BIRTH" in line:
        date = lines[line_number + 2] # Date is also always two lines after
    elif "BIO" in line:
        for x in range(line_number + 1, line_number + 20): # Length of other data can be randomly bigger
            if "HOBBIES" not in lines[x]:
                bio += lines[x]
            else:
                break
    elif "HOBBIES" in line:
        #...
这已经足够好了,但我觉得应该有一种更聪明、更少黑客的方法来代替许多双循环

我正在寻找一个通用的解决方案,其中NAME会将所有东西存储到出生日期,BIO会将所有东西存储到业余爱好等,目的是在以后清理和去除多余的白色绒毛

可能吗

编辑:当我阅读答案时,我意识到我忘记了一个非常重要的细节,按键有时会重复(以相同的顺序)


也就是说,一个文本文件可以包含多个人。应创建人员列表。键名标志着一个新人的开始。

我将所有内容都存储在字典中,请参见下面的代码

f=open(“test.txt”)
行=f.读行()
dict_text={“姓名”:[],“出生日期”:[],“个人简历”:[]}
对于行_编号,枚举中的行(行):
如果不是(“姓名”一行或“出生日期”一行或“个人简历”一行):
text=行。替换(“\n”和“”)
dict_text[位置].追加(文本)
其他:
location=”“.join((line.split()))

我将所有内容存储在字典中,请参见下面的代码

f=open(“test.txt”)
行=f.读行()
dict_text={“姓名”:[],“出生日期”:[],“个人简历”:[]}
对于行_编号,枚举中的行(行):
如果不是(“姓名”一行或“出生日期”一行或“个人简历”一行):
text=行。替换(“\n”和“”)
dict_text[位置].追加(文本)
其他:
location=”“.join((line.split()))

您可以使用正则表达式:

import re

keys = """
NAME
DATE OF BIRTH
BIO 
HOBBIES 
""".strip().splitlines()

key_pattern = '|'.join(f'{key.strip()}' for key in keys)
pattern = re.compile(fr'^({key_pattern})', re.M)

# uncomment to see the pattern
# print(pattern)

with open(filename) as f:
    text = f.read()
    parts = pattern.split(text)

... process parts ...

部分
将是一个列表字符串。奇数索引位置(
部分[1]
部分[3]
,…)将是键('NAME',等),偶数索引位置(
部分[2]
部分[4]
,…)将是键之间的文本<代码>部分[0]将是第一个键之前的内容。

您可以使用正则表达式:

import re

keys = """
NAME
DATE OF BIRTH
BIO 
HOBBIES 
""".strip().splitlines()

key_pattern = '|'.join(f'{key.strip()}' for key in keys)
pattern = re.compile(fr'^({key_pattern})', re.M)

# uncomment to see the pattern
# print(pattern)

with open(filename) as f:
    text = f.read()
    parts = pattern.split(text)

... process parts ...

部分
将是一个列表字符串。奇数索引位置(
部分[1]
部分[3]
,…)将是键('NAME',等),偶数索引位置(
部分[2]
部分[4]
,…)将是键之间的文本<代码>部分[0]将是第一个键之前的内容。

您可以尝试以下操作

keys = ["NAME","DATE OF BIRTH","BIO","HOBBIES"]

f = open("data.txt", "r")
result = {}
for line in f:
    line = line.strip('\n')
    if any(v in line for v in keys):
        last_key = line
    else:
        result[last_key] = result.get(last_key, "") + line

print(result)
输出

{'NAME': 'John Doe', 'DATE OF BIRTH': '1992-02-16', 'BIO ': 'THIS is a PRETTY long sentence without ANY structure ', 'HOBBIES ': '//..etc..'}

您可以尝试以下方法

keys = ["NAME","DATE OF BIRTH","BIO","HOBBIES"]

f = open("data.txt", "r")
result = {}
for line in f:
    line = line.strip('\n')
    if any(v in line for v in keys):
        last_key = line
    else:
        result[last_key] = result.get(last_key, "") + line

print(result)
输出

{'NAME': 'John Doe', 'DATE OF BIRTH': '1992-02-16', 'BIO ': 'THIS is a PRETTY long sentence without ANY structure ', 'HOBBIES ': '//..etc..'}

您可以将文件转换为一个长字符串,而不是读取行。使用string.index()查找触发器字的开始索引,然后将从该索引到下一个触发器字索引的所有内容设置为变量

比如:

string = str(f)
important_words = ['NAME', 'DATE OF BIRTH']
last_phrase = None
for phrase in important_words:
   phrase_start = string.index(phrase)
   phrase_end = phrase_start + len(phrase)
   if last_phrase is not None:
      get_data(string, last_phrase, phrase_start)
   last_phrase = phrase_end

def get_data(string, previous_end_index, current_start_index):
   usable_data = string[previous_end_index: current_start_index]
   return usable_data

可能应该使用更好/更短的变量名,而不是将文件转换为一个长字符串。使用string.index()查找触发器字的开始索引,然后将从该索引到下一个触发器字索引的所有内容设置为变量

比如:

string = str(f)
important_words = ['NAME', 'DATE OF BIRTH']
last_phrase = None
for phrase in important_words:
   phrase_start = string.index(phrase)
   phrase_end = phrase_start + len(phrase)
   if last_phrase is not None:
      get_data(string, last_phrase, phrase_start)
   last_phrase = phrase_end

def get_data(string, previous_end_index, current_start_index):
   usable_data = string[previous_end_index: current_start_index]
   return usable_data

可能应该使用更好/更短的变量名

您只需读取一个长字符串中的文本即可。然后使用.split() 这只有在类别有序且不重复的情况下才有效。 就这样,


您可以只读取一个长字符串中的文本。然后使用.split() 这只有在类别有序且不重复的情况下才有效。 就这样,


你熟悉状态机的概念吗?如果没有,请尝试查找它,看看是否可以想出一种方法将该原则应用到代码中。您还可以使用模式来获取特定的匹配项您熟悉状态机的概念吗?如果没有,试着查找它,看看你是否能想出一种方法将这个原则应用到你的代码中。你也可以使用一个模式来获得特定的匹配