我使用python以块的形式读取了一个巨大的文件。然后我在那个块上应用正则表达式。基于标识符标记,我想提取相应的值。由于块大小,块边界处缺少数据。
要求:
Python代码示例
identifier_pattern = re.compile(r'Identifier: (.*?)\n')
with open('huge_file', 'r') as f:
data_chunk = f.read(1024*1024*1024)
m = re.findall(identifier_pattern, data_chunk)
块数据示例
好:与标识数相等的标记数
标识符:值
标识符:值
标识符:值
标识符:值
由于块大小,您会遇到如下所列的不同边界问题。第三个标识符返回一个不完整的值," v"而不是"价值"。下一个块包含" alue"。这会在解析后导致丢失数据。
错误:标识符值不完整
标识符:值
标识符:值
标识符:v
你如何解决像这样的块边界问题?
答案 0 :(得分:3)
假设这是你的确切问题,你可能只需调整你的正则表达式并逐行读取(它不会将整个文件加载到内存中):
import re
matches = []
identifier_pattern = re.compile(r'Identifier: (.*?)$')
with open('huge_file') as f:
for line in f:
matches += re.findall(identifier_pattern, line)
print("matches", matches)
答案 1 :(得分:2)
你可以控制块形成并使其接近1024 * 1024 * 1024,在这种情况下你可以避免遗漏部分:
import re
identifier_pattern = re.compile(r'Identifier: (.*?)\n')
counter = 1024 * 1024 * 1024
data_chunk = ''
with open('huge_file', 'r') as f:
for line in f:
data_chunk = '{}{}'.format(data_chunk, line)
if len(data_chunk) > counter:
m = re.findall(identifier_pattern, data_chunk)
print m.group()
data_chunk = ''
# Analyse last chunk of data
m = re.findall(identifier_pattern, data_chunk)
print m.group()
或者,你可以在不同起始点read
的同一个文件上进行两次(第一次从0开始,第二次从第一次迭代中收集的匹配字符串的最大长度开始),将结果存储为字典,其中key=[start position of matched string in file]
,每个迭代的位置都是相同的,因此合并结果不会有问题,但我认为按照匹配字符串的起始位置和长度进行合并会更准确。
祝你好运!
答案 2 :(得分:1)
如果文件基于行,file
对象是懒惰的行生成器,它会将文件加载到内存行按行(在块中),基于此,您可以使用:
import re
matches = []
for line in open('huge_file'):
matches += re.findall("Identifier:\s(.*?)$", line)
答案 3 :(得分:0)
我的解决方案与杰克的答案非常相似:
#!/usr/bin/env python3
import re
identifier_pattern = re.compile(r'Identifier: (.*)$')
m = []
with open('huge_file', 'r') as f:
for line in f:
m.extend(identifier_pattern.findall(line))
您可以使用正则表达式API的另一部分来获得相同的结果:
#!/usr/bin/env python3
import re
identifier_pattern = re.compile(r'Identifier: (.*)$')
m = []
with open('huge_file', 'r') as f:
for line in f:
pattern_found = identifier_pattern.search(line)
if pattern_found:
value_found = pattern_found.group(0)
m.append(value_found)
我们可以使用generator expression和list comprehension
进行简化#!/usr/bin/env python3
import re
identifier_pattern = re.compile(r'Identifier: (.*)$')
with open('huge_file', 'r') as f:
patterns_found = (identifier.search(line) for line in f)
m = [pattern_found.group(0)
for pattern_found in patterns_found if pattern_found]
答案 4 :(得分:0)
如果知道匹配结果字符串的长度,我认为最简单的方法是将最后一块的字节缓存在边界周围。
假设结果的长度为3,保留最后一块的最后2个字符,然后将其添加到新块中进行匹配。
伪代码:
regex pattern
string boundary
int match_result_len
for chunk in chunks:
match(boundary + chunk, pattern)
boundary = chunk[-(match_result_len - 1):]