【问题标题】:find and delete lines in file python 3在文件python 3中查找和删除行
【发布时间】:2012-06-12 19:16:27
【问题描述】:

我使用 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

我为此做了很多尝试,但无法让它发挥作用。

【问题讨论】:

    标签: file python-3.x


    【解决方案1】:

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

    您可以构建一个字典,其中 id 号是键(由于稍后的排序而转换为 int),以下行将转换为作为键值的字符串列表。然后可以删除key为2的item,遍历key排序的item,输出新的id:key加上格式化后的字符串列表。

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

    这可以为一个合理大小的文件完成。如果文件很大,您应该将源文件复制到目标文件并即时跳过不需要的序列。对于小文件,最后一种情况也相当容易。

    [澄清后添加]

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

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

    代码一开始可能看起来很复杂,但是当您知道可以分别考虑每个if status == number 时,它就很容易理解了。这是捕获先前处理的提到的上下文。不要试图优化,让代码那样吧。它实际上可以稍后进行人工解码,并且您可以绘制类似于Mealy machine example的图片。如果你这样做了,那就更容易理解了。

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

    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 行。如果要重新编号这些部分,可以通过简单的修改来完成。尝试代码并询问详细信息。

    请注意,有限自动机的功能有限。它们不能用于通常的编程语言,因为它们无法捕获嵌套的成对结构(如双亲)。

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

    【讨论】:

    • id用于dscision删除序列,文件包含7.000行,所以它很大。很抱歉我提供的信息太少了。
    • @user1229391:删除序列后,下一个序列应该保持原来的编号,还是应该更正(递减)它们的id?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      如果两者之间没有任何值会干扰这将起作用....

      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 ... 你可以修改它,以便第一个 if 检查 - line == "id:" + number

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-02
        • 2021-10-14
        • 1970-01-01
        • 2013-07-24
        • 1970-01-01
        • 2017-05-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多