繁体   English   中英

python在文件中搜索字符串,将整行+下一行返回新文本文件

[英]python search for string in file return entire line + next line into new text file

我有一个非常大的文本文件(50,000行以上),应始终以相同的顺序进行。 在python中,我想在文本文件中搜索$ INGGA的每一行,并将此行与随后的$ INHDT合并以创建一个新的文本文件。 我需要在不读取内存的情况下执行此操作,因为这会导致每次崩溃。 我可以找到返回$ INGGA行的方法,但是我不确定获得下一行并连接到内存效率高的新字符串的最佳方法

谢谢

菲尔

=〜=〜=〜=〜=〜=〜=〜=〜=〜=〜=〜= PuTTY日志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,M,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,M,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,M,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,M,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,M,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 $ PRDI D,2.09,0.02,42.42 * 40 $ INGGA,091125.00,5249.8347,N,00120.9610,W,1,20,0.6,95.1,M,49.4,M ,, * 5F $ INHDT,42.4,T * 17

您可以只读取一行文件并写入另一个新文件。 像这样:

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追加write和wt来读取行!

我有150,000行文件,运行良好!

我建议使用一个简单的正则表达式来解析和捕获您关心的部分。 这是一个示例,它将捕获您关心的部分:

(\\$INGGA.*\\n\\$INHDT.*\\n)

https://regex101.com/r/tK1hF0/3

在上面的链接中,您会注意到我在正则表达式上使用了“ global” g设置,告诉它捕获所有匹配的组。 否则,它将在第一场比赛后停止。

在确定上述示例文件中实际的换行符的位置时,我也遇到了麻烦,因此您可以对上述内容进行调整,以准确匹配出现换行符的位置。

这是一些入门python示例代码:

import re

test_str = # load your file here

p = re.compile(ur'(\$INGGA.*\n\$INHDT.*\n)')
matches = re.findall(p, test_str)

在您提供的示例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

此答案针对python 3。

根据这个其他答案 (和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,'之前有多个'$INGGA,' '$INHDT,' ,则这将抢占第一个,而忽略其余的。 如果您只想取最后的'$INGGA,''$INGGA,'之前'$INHDT,' ,则将最后的'$INGGA,'在变量中,而不是将其写入磁盘。 然后,当您找到'$INHDT,' ,请同时存储两者。
  • 如果您要为每个INGGA-INHDT对写入一个单独的新文件,则with -statement的目标文件应嵌套for line in sf ,或者将结果缓冲在列表中以备后用。

请参阅文档以获取with -statements文件读取/写入的介绍

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM