我有一个非常大的文本文件(50,000多行),它们应始终采用相同的顺序。在python中,我想搜索每个$ INGGA行的文本文件,并将此行与后续的$ INHDT连接以创建新的文本文件。我需要这样做而不读入内存,因为这会导致它每次都崩溃。我可以找到返回$ INGGA线但是我不确定最好的方法然后获得下一行并加入一个内存有效的新字符串
由于
菲尔
=〜=〜=〜=〜=〜=〜=〜=〜=〜=〜=〜= PuTTY log 2016.05.06 09:11:34 =〜=〜=〜=〜=〜=〜=〜 =〜=〜=〜=〜=> $ PRDID,2.15,-0.10,31.87 * 6E $ INGGA,091124.00,5249.8336,N,00120.9619,W,1,20,0.6,95.0,男,49.4,M,* 50 $ INHDT,31.9,T * 1E $ INZDA,091124.0055,06,05,2016 ,, * 7F $ INVTG,22.0,T ,, M,4.4,N,8.1,K,A * 24 $ PRDID,2.13,-0.06,34.09 * 6C $ INGGA,091124.20,5249.8338,N,00120.9618,W,1,20,0.6,95.0,男,49.4,M,* 5D $ INHDT,34.1,T * 13 $ INZDA,091124.2055,06,05,2016 ,, * 7D $ INVTG,24.9,T ,, M,4.4,N,8.1,K,A * 2B $ PRDID,2.16,-0.03,36.24 * 61 $ INGGA,091124.40,5249.8340,N,00120.9616,W,1,20,0.6,95.0,男,49.4,M,* 5A $ INHDT,36.3,T * 13 $ INZDA,091124.4055,06,05,2016 ,, * 7B $ INVTG,27.3,T ,, M,4.4,N,8.1,K,A * 22 $ PRDID,2.11,-0.05,38.33 * 68 $ INGGA,091124.60,5249.8343,N,00120.9614,W,1,20,0.6,95.1,男,49.4,M,* 58 $ INHDT,38.4,T * 1A $ INZDA,091124.6055,06,05,2016 ,, * 79 $ INVTG,29.5,T ,, M,4.4,N,8.1,K,A * 2A $ PRDID,2.09,-0.02,40.37 * 6D $ INGGA,091124.80,5249.8345,N,00120.9612,W,1,20,0.6,95.1,男,49.4,M,* 56 $ INHDT,40.4,T * 15 $ INZDA,091124.8055,06,05,2016 ,, * 77 $ INVTG,31.7,T ,, M,4.4,N,8.1,K,A * 21 $ PRDID,2.09,0.02,42.42 * 40 $ INGGA,091125.00,5249.8347,N,00120.9610,W,1,20,0.6,95.1,男,49.4,M,* 5F $ INHDT,42.4,T * 17
答案 0 :(得分:2)
您只需读取一行文件并写入另一个新文件即可。 像这样:
import re
#open new file with append
nf = open('newfile', 'at')
#open file with read
with open('file', 'rt') as f:
for line in f:
r = re.match(r'\$INGGA', line)
if r is not None:
nf.write(line)
nf.write("$INHDT,31.9,T*1E" + '\n')
您可以使用at
附加写入和wt
来读取行!
我有150,000行文件,它运行良好!
答案 1 :(得分:0)
我建议使用一个简单的正则表达式来解析和捕获你关心的部分。这是一个捕捉你关注的作品的例子:
(\$INGGA.*\n\$INHDT.*\n)
https://regex101.com/r/tK1hF0/3
在上面的链接中,您会注意到我在正则表达式上使用了“全局”g设置,告诉它捕获匹配的所有组。否则,它将在第一场比赛后停止。
我也无法确定上述示例文件中实际换行符的位置,因此您可以调整上述内容以准确匹配中断发生的位置。
这是一些启动python示例代码:
import re
test_str = # load your file here
p = re.compile(ur'(\$INGGA.*\n\$INHDT.*\n)')
matches = re.findall(p, test_str)
答案 2 :(得分:0)
在示例PuTTY日志中,它给出了所有一行用空格分隔的行。 因此,在这种情况下,您可以使用它来用新行替换空格并获取新文件 -
cat large_file | sed 's/ /\n/g' > new_large_file
要迭代用新行分隔的文件,请运行 -
cat new_large_file | python your_script.py
您的脚本逐行获取,因此您的计算机不会崩溃。
your_script.py -
import sys
INGGA_line = ""
for line in sys.stdin:
line_striped = line.strip()
if line_striped.startswith("$INGGA"):
INGGA_line = line_striped
elif line_striped.startswith("$INZDA"):
print line_striped, INGGA_line
else:
print line_striped
答案 3 :(得分:0)
这个答案针对的是python 3。
根据this other answer(和the docs),您可以有效地逐行内存迭代文件:
with open(filename, 'r') as f:
for line in f:
...process...
您可以如何实现上述标准的示例
# Target file write-only, source file read-only
with open(targetfile, 'w') as tf, open(sourcefile, 'r') as sf:
# Flag for whether we are looking for 1st or 2nd part
look_for_ingga = True
for line in sf:
if look_for_ingga:
if line.startswith('$INGGA,'):
tf.write(line)
look_for_ingga = False
elif line.startswith('$INHDT,'):
tf.write(line)
look_for_ingga = True
'$INGGA,'
之前有多个'$INHDT,'
,则会抓取第一个并忽略其余的'$INGGA,'
。{li>如果您只想在'$INHDT,'
之前使用最后'$INGGA,'
,请将最后'$INHDT,'
存储在变量中,而不是将其写入磁盘。然后,当您找到with
时,请同时存储。{/ li>
for line in sf
- 语句应该嵌套在is_string()
内,或者结果应该是缓存在列表中以便以后存储。请参阅文档,了解with
-statements和file reading/writing的介绍。