File 查找并删除文件python 3中的行

File 查找并删除文件python 3中的行,file,python-3.x,File,Python 3.x,我使用python 3 好的,我有一个这样的文件: id:1 1 34 22 52 id:2 1 23 22 31 id:3 2 12 3 31 id:4 1 21 22 11 如何仅查找和删除文件的这一部分 id:2 1 23 22 31 我一直在尝试这么做,但无法让它工作。将每一行读入一个字符串数组。索引号是行号-1。在阅读该行之前,请检查该行是否等于“id:2”。如果是,则停止读取该行,直到该行等于“id:3”。读取行后,清除文件并将数组写回文件,直到数组结束。这可能不是最有效的方法,

我使用python 3

好的,我有一个这样的文件:

id:1
1
34
22
52
id:2
1
23
22
31
id:3
2
12
3
31
id:4
1
21
22
11
如何仅查找和删除文件的这一部分

id:2
1
23
22
31

我一直在尝试这么做,但无法让它工作。

将每一行读入一个字符串数组。索引号是行号-1。在阅读该行之前,请检查该行是否等于“id:2”。如果是,则停止读取该行,直到该行等于“id:3”。读取行后,清除文件并将数组写回文件,直到数组结束。这可能不是最有效的方法,但应该有效。

是用于决定删除序列的id,还是用于决定的值列表

您可以构建一个字典,其中id号是键(由于后面的排序转换为int),下面的行转换为作为键值的字符串列表。然后可以使用键2删除该项,遍历按键排序的项,并输出新的id:key和格式化的字符串列表

或者,您可以在保护订单的位置构建列表列表。如果要保护id序列(即不重新编号),您还可以记住内部列表中的id:n

对于大小合理的文件,可以这样做。如果文件很大,则应将源文件复制到目标文件,并动态跳过不需要的序列。最后一个案例对于小文件来说也相当容易

[澄清后添加]

我建议学习以下方法,这在许多此类情况下都很有用。它使用所谓的有限自动机来实现绑定到从一个状态到另一个状态的转换的操作(请参阅)

文本行是此处的输入元素。表示上下文状态的节点在此处编号。(根据我的经验,给他们起名字是不值得的——只保留愚蠢的数字。)这里只使用了两种状态,
status
可以很容易地被布尔变量替换。但是,如果情况变得更复杂,则会引入另一个布尔变量,代码更容易出错

代码一开始可能看起来很复杂,但如果status==number可以分别考虑每个
,那么就很容易理解了。这就是所提到的捕获了先前处理的上下文。不要试图优化,让代码这样。事实上,它可以在以后被人类解码,你可以画出类似的图片。如果你这样做了,那就更容易理解了

想要的功能有点通用化——可以将一组被忽略的部分作为第一个参数传递:

import re

def filterSections(del_set, fname_in, fname_out):
    '''Filtering out the del_set sections from fname_in. Result in fname_out.'''

    # The regular expression was chosen for detecting and parsing the id-line.
    # It can be done differently, but I consider it just fine and efficient.
    rex_id = re.compile(r'^id:(\d+)\s*$')

    # Let's open the input and output file. The files will be closed
    # automatically.
    with open(fname_in) as fin, open(fname_out, 'w') as fout:
        status = 1                 # initial status -- expecting the id line
        for line in fin:
            m = rex_id.match(line) # get the match object if it is the id-line

            if status == 1:      # skipping the non-id lines
                if m:              # you can also write "if m is not None:"
                    num_id = int(m.group(1))  # get the numeric value of the id
                    if num_id in del_set:     # if this id should be deleted
                        status = 1            # or pass (to stay in this status)
                    else:
                        fout.write(line)      # copy this id-line
                        status = 2            # to copy the following non-id lines
                #else ignore this line (no code needed to ignore it :)

            elif status == 2:      # copy the non-id lines
                if m:                         # the id-line found
                    num_id = int(m.group(1))  # get the numeric value of the id
                    if num_id in del_set:     # if this id should be deleted
                        status = 1            # or pass (to stay in this status)
                    else:
                        fout.write(line)      # copy this id-line
                        status = 2            # to copy the following non-id lines
                else:
                    fout.write(line)          # copy this non-id line


if __name__ == '__main__':
    filterSections( {1, 3}, 'data.txt', 'output.txt')
    # or you can write the older set([1, 3]) for the first argument.
这里是给定原始编号的输出id行。如果你想重新编号的部分,它可以通过一个简单的修改。尝试代码并询问详细信息

注意,有限自动机的能力有限。它们不能用于常规编程语言,因为它们不能捕获嵌套的成对结构(如parentese)


另外,从计算机的角度来看,7000行实际上是一个很小的文件;)

如果中间没有任何会干扰的值,这将起作用

import fileinput 
...
def deleteIdGroup( number ):
    deleted = False
    for line in fileinput.input( "testid.txt", inplace = 1 ):
        line = line.strip( '\n' )
        if line.count( "id:" + number ): # > 0
            deleted = True;
        elif line.count( "id:" ): # > 0
            deleted = False;
        if not deleted:
            print( line )
编辑:


抱歉,此操作将删除id:2和id:20。。。yuo可以修改它,以便第一个if checks-line==“id:+number

该id用于数据决定删除序列,并且该文件包含7.000行,因此它很大。很抱歉,我提供的信息少了。@user1229391:删除序列后,下一个序列应该保留原始编号,还是应该更正(递减)它们的id?