2012-08-24 116 views
0

我有以下的文本文件:刪除文本文件的某些行蟒蛇

This is my text file 
NUM,123 
FRUIT 
DRINK 
FOOD,BACON 
CAR 
NUM,456 
FRUIT 
DRINK 
FOOD,BURGER 
CAR 
NUM,789 
FRUIT 
DRINK 
FOOD,SAUSAGE 
CAR 
NUM,012 
FRUIT 
DRINK 
FOOD,MEATBALL 
CAR 

而且我叫下面的列表中「想」:

['123', '789'] 

我想要做的如果NUM後面的數字不在名爲'wanted'的列表中,則該行以及其下面4行會被刪除。因此,輸出文件將是這樣的:

This is my text file 
NUM,123 
FRUIT 
DRINK 
FOOD,BACON 
CAR 
NUM,789 
FRUIT 
DRINK 
FOOD,SAUSAGE 
CAR 

到目前爲止我的代碼是:

infile = open("inputfile.txt",'r') 
data = infile.readlines() 

for beginning_line, ube_line in enumerate(data): 
    UNIT = data[beginning_line].split(',')[1] 
    if UNIT not in wanted: 
     del data_list[beginning_line:beginning_line+4] 
+0

您的代碼是否正常工作?如果不是,你得到的錯誤是什麼? –

+2

你的代碼和文字說你想刪除'wanted'中的__not__;你的例子表明否則。 –

+0

當我'打印ube_line'時,它不輸出正確的東西。我正在嘗試寫入一個新文件。 – user1546610

回答

4

您在循環播放時不應修改列表。

什麼你可以嘗試是剛剛推進文件對象上的迭代器在需要的時候:

wanted = set(['123', '789']) 

with open("inputfile.txt",'r') as infile, open("outfile.txt",'w') as outfile: 
    for line in infile: 
     if line.startswith('NUM,'): 
      UNIT = line.strip().split(',')[1] 
      if UNIT not in wanted: 
       for _ in xrange(4): 
        infile.next() 
       continue 

     outfile.write(line) 

並使用一組。經常檢查會員的速度更快。

此方法不會讓您一次讀入整個文件以列表形式處理它。它一行一行,從文件中讀取,前進,並寫入新文件。如果你願意,你可以用你正在追加的列表替換outfile。

+0

是否可以將其寫回輸入文件? – user1546610

+0

直到你先讀完所有東西之後。你想要做的是使outfile成爲臨時文件。然後,當整個事情成功時,你將outfile移到infile上。 – jdi

0

編輯:刪除項目,而迭代可能不是一個好主意,請參見:Remove items from a list while iterating

infile = open("inputfile.txt",'r') 
data = infile.readlines() 
SKIP_LINES = 4 
skip_until = False 

result_data = [] 
for current_line, line in enumerate(data): 
    if skip_until and skip_until < current_line: 
     continue 

    try: 
     _, num = line.split(',') 
    except ValueError: 
     pass 
    else: 
     if num not in wanted: 
      skip_until = current_line + SKIP_LINES 
     else: 
      result_data.append(line) 

...和result_data是你想要的。

0

代碼存在一些問題;例如,data_list甚至沒有定義。如果它是list,則不能從中獲得del元素;你只能pop。然後你使用enumeratedata直接索引訪問;也不需要readlines

我建議避免保留內存中的所有行,這裏並不是真的需要。喜歡的東西(未經測試)也許嘗試:

with open('infile.txt') as fin, open('outfile.txt', 'w') as fout: 
    for line in fin: 
     if line.startswith('NUM,') and line.split(',')[1] not in wanted: 
      for _ in range(4): 
       fin.next() 
     else: 
      fout.write(line) 
0
import re 
# find the lines that match NUM,XYZ 
nums = re.compile('NUM,(?:' + '|'.join(['456','012']) + ")") 
# find the three lines after a nums match 
line_matches = breaks = re.compile('.*\n.*\n.*\n') 
keeper = '' 
for line in nums.finditer(data): 
    keeper += breaks.findall(data[line.start():])[0] 

結果給定的字符串是

NUM,456 
FRUIT 
DRINK 
FOOD,BURGER 

NUM,012 
FRUIT 
DRINK 
FOOD,MEATBALL 
0

如果你不介意建立一個列表,當且僅當和你"NUM"線來每5其他線路,你可以嘗試:

keep = [] 
for (i, v) in enumerate(lines[::5]): 
    (num, current) = v.split(",") 
    if current in wanted: 
     keep.extend(lines[i*5:i*5+5]) 
0

不要試圖想出這個建立一個列表和REM在你循環播放時從它中取出東西。那樣會導致瘋狂。

直接編寫輸出文件要容易得多。循環輸入文件的行,每次決定是否將它寫入輸出。

此外,爲避免不是所有行都有逗號的問題,請嘗試使用.partition來代替行。這將總是返回3個項目:當有逗號時,(在第一個逗號之前,逗號之後,逗號之後);否則,你會得到(整個事情,空字符串,空字符串)。所以你可以使用最後一項,因爲wanted不會包含空字符串。

skip_counter = 0 
for line in infile: 
    if line.partition(',')[2] not in wanted: 
     skip_counter = 5 
    if skip_counter: 
     skip_counter -= 1 
    else: 
     outfile.write(line)