簡體   English   中英

如何根據正則表達式模式將文本文件拆分為較小的文件?

[英]How to split a text file into smaller files based on regex pattern?

我有一個如下所示的文件:

SCN DD1251       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
        DD1271      C           DD1271    R                                     
        DD1351      D           DD1351    B                                     
                    E                                                           
                                                                                
SCN DD1271       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
        DD1301      T           DD1301    A                                     
        DD1251      R           DD1251    C                                     
                                                                                
SCN DD1301       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
        DD1271      A           DD1271    T                                     
                    B                                                           
                    C                                                           
                    D                                                           
                                                                                
SCN DD1351       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
                    A           DD1251    D                                     
        DD1251      B                                                           
                    C                                                           
                                                                                
SCN DD1451       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
                    A                                                           
                    B                                                           
                    C                                                           
                                                                                
SCN DD1601       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
                    A                                                           
                    B                                                           
                    C                                                           
                    D                                                           
                                                                                
SCN GA0101       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
                    B           GC4251    D                                     
        GC420A      C           GA127A    S                                     
        GA127A      T                                                           
                                                                                
SCN GA0151       
            UPSTREAM               DOWNSTREAM               FILTER              
          NODE     LINK          NODE    LINK                LINK               
                    C           GA0401    R                   G                 
        GA0201      D           GC0051    E                   H                 
        GA0401      B           GA0201    W                                     
        GC0051      A                                                           

每條記錄之間的間隙有一個換行符,后跟 81 個空格。

我使用 regex101.com 創建了以下正則表達式,它似乎與每條記錄之間的差距相匹配:

\s{81}\n

結合下面的短循環打開文件,然后將每個部分寫入一個新文件:

delimiter_pattern = re.compile(r"\s{81}\n")

with open("Junctions.txt", "r") as f:
    i = 1
    for line in f:
        if delimiter_pattern.match(line) == False:
            output = open('%d.txt' % i,'w')
            output.write(line)
        else:
            i+=1

但是,不是輸出,而是像下面預期的那樣說 2.txt:

SCN DD1271
            UPSTREAM               DOWNSTREAM               FILTER
          NODE     LINK          NODE    LINK                LINK
        DD1301      T           DD1301    A
        DD1251      R           DD1251    C

相反,它似乎什么也沒有返回。 我試過像這樣修改代碼:

with open("Clean-Junction-Links1.txt", "r") as f:
    i = 1
    output = open('%d.txt' % i,'w')
    for line in f:
        if delimiter_pattern.match(line) == False:
            output.write(line)
        else:
            i+=1

但這反而會返回數百個空白文本文件。

我的代碼有什么問題,我該如何修改它以使其工作? 如果失敗,是否有更簡單的方法可以在不使用正則表達式的情況下在空行上拆分文件?

您不需要使用正則表達式來執行此操作,因為您可以使用 string strip()方法輕松檢測塊之間的間隙。

input_file = 'Clean-Junction-Links1.txt'

with open(input_file, 'r') as file:
    i = 0
    output = None

    for line in file:
        if not line.strip():  # Blank line?
            if output:
                output.close()
            output = None
        else:
            if output is None:
                i += 1
                print(f'Creating file "{i}.txt"')
                output = open(f'{i}.txt','w')
            output.write(line)

    if output:
        output.close()

print('-fini-')

另一種更簡潔、更模塊化的實現方式是將處理分成兩個獨立的任務,這些任務在邏輯上彼此幾乎沒有關系:

  1. 讀取文件並將每個記錄的行分組在一起。
  2. 將每組行寫入單獨的文件。

第一個可以實現為生成器函數,該函數迭代地收集並生成包含記錄的行組。 它是下面名為extract_records()的那個。

input_file = 'Clean-Junction-Links1.txt'

def extract_records(filename):
    with open(filename, 'r') as file:
        lines = []
        for line in file:
            if line.strip():  # Not blank?
                lines.append(line)
            else:
                yield lines
                lines = []
        if lines:
            yield lines

for i, record in enumerate(extract_records(input_file), start=1):
    print(f'Creating file {i}.txt')
    with open(f'{i}.txt', 'w') as output:
        output.write(''.join(record))

print('-fini-')

\\s捕獲空格和換行符,所以它是 80 個空格加一個換行符得到 {81}。 在逐行迭代時, for line in f的行,您無法獲得第二個換行符,除非您添加了額外的邏輯來解決這個問題。 此外, match()返回 None,而不是 False。

#! /usr/bin/env python3
import re

delimiter_pattern = re .compile( r'\s{81}' )

with open( 'Junctions.txt', 'r' ) as f:
    i = 1
    for line in f:
        if delimiter_pattern .match( line ) == None:
            output = open( f'{i}.txt', 'a+' )
            output .write( line )
        else:
            i += 1

您得到空白輸出,因為您正在檢查一行是否與一堆空格( \\s{81}\\n )匹配,如果匹配,則您只寫入該(空白)行。 您需要在讀取時打印每一行,然后在模式匹配時跳轉到新文件。

此外,當您for line in f使用for line in f\\n字符將被刪除,因此您的正則表達式將不匹配。

import re

delimiter_pattern = re.compile(r"\s{81}")

with open("Junctions.txt", "r") as f:
    fileNum = 1
    output = open(f'{fileNum}.txt','w') # f-strings require Python 3.6 but are cleaner
    for line in f:
        if not delimiter_pattern.match(line):
            output.write(line)
        else:
            output.close()
            fileNum += 1
            output = open(f'{fileNum}.txt','w')

    # Close last file
    if not output.closed:
      output.close()

一些東西。

  1. 正在生成單個文本文件,因為您沒有在循環中打開用於寫入的文件,而是在循環開始之前打開一個文件。

  2. 根據所需的輸出,您不希望在每一行上匹配正則表達式,而是希望繼續讀取文件,直到獲得單個記錄。

我已經整理了一個可行的解決方案

with open("Junctions.txt", "r") as f:
        #read file and split on 80 spaces followed by new line
        file = f.read()
        sep = " " * 80 + "\n"
        chunks = file.split(sep)

        #for each chunk of the file write to a txt file
        i = 0
        for chunk in chunks:
            with open('%d.txt' % i, 'w') as outFile:
                outFile.write(chunk)
            i += 1

這將獲取文件並通過找到一個分隔符(80 個空格后跟新行)來獲取您想要的所有組的列表

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM