![](/img/trans.png)
[英]Python3 How to split a large text file into smaller files based on line content
[英]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-')
另一種更簡潔、更模塊化的實現方式是將處理分成兩個獨立的任務,這些任務在邏輯上彼此幾乎沒有關系:
第一個可以實現為生成器函數,該函數迭代地收集並生成包含記錄的行組。 它是下面名為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()
一些東西。
正在生成單個文本文件,因為您沒有在循環中打開用於寫入的文件,而是在循環開始之前打開一個文件。
根據所需的輸出,您不希望在每一行上匹配正則表達式,而是希望繼續讀取文件,直到獲得單個記錄。
我已經整理了一個可行的解決方案
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.