2013-05-06 3 views
2

Я пытаюсь удалить определенные номера строк из файла в Python в пути, такие какпитона удалить «многие» строку из файла

./foo.py filename.txt 4 5 2919

Где 4 5 и 2919 являются номерами строк

То, что я пытаюсь сделать, это:

for i in range(len(sys.argv)): 
    if i>1: # Avoiding sys.argv[0,1] 
     newlist.append(int(sys.argv[i])) 

Тогда:

count=0 

generic_loop{ 
    bar=file.readline() 
    count+=1 
    if not count in newlist: 
     print bar 
} 

печатает все строки в исходном файле (с пробелами между ними)

+2

Что такое generic_loop? Было бы лучше, если бы вы разместили реальный код, а не поддельный код. –

+0

Я боялся, что это может показаться слишком специфичным, поэтому я сделал это так. – Mansueli

+1

Я также призываю вас использовать ['argparse'] (http://docs.python.org/dev/library/argparse.html). Если вы используете 'type = int' и' nargs = '*' ', вам не нужно иметь дело с' sys.argv', и вы получите отличные сообщения об ошибках/использовании бесплатно. – Felipe

ответ

2

Вы можете попробовать что-то вроде этого:

import sys 
import os 
filename= sys.argv[1] 
lines = [int(x) for x in sys.argv[2:]] 

#open two files one for reading and one for writing 

with open(filename) as f,open("newfile","w") as f2: 

#use enumerate to get the line as well as line number, use enumerate(f,1) to start index from 1 
    for i,line in enumerate(f): 
     if i not in lines:  #`if i not in lines` is more clear than `if not i in line` 
      f2.write(line) 
os.rename("newfile",filename) #rename the newfile to original one  

Обратите внимание, что для создания временных файлов, что лучше использовать tempfile модуль.

+1

Остерегайтесь; это не зависит от потоков или процессов; если несколько процессов запускают эту программу параллельно, они, вероятно, перезапишут временный файл. Используйте вместо этого модуль ['tempfile'] (http://docs.python.org/dev/library/tempfile.html). – phihag

+0

@phihag Спасибо за предложение, я никогда не слышал о «tempfile» раньше. –

3

Вы можете использовать enumerate определить номер строки:

import sys 
exclude = set(map(int, sys.argv[2:])) 
with open(sys.argv[1]) as f: 
    for num,line in enumerate(f, start=1): 
     if num not in exclude: 
      sys.stdout.write(line) 

Вы можете удалить start=1 при запуске считая в 0. В приведенном выше коде нумерация строк начинается с 1:

$ python3 so-linenumber.py so-linenumber.py 2 4 5 
import sys 
with open(sys.argv[1], 'r') as f: 
      sys.stdout.write(line) 

Если вы хотите написать контент самому файлу, напишите его в temporary file вместо sys.stdout, а затем rename, чтобы исходное имя файла (или используйте sponge в командной строке), например:

import os 
import sys 
from tempfile import NamedTemporaryFile 
exclude = set(map(int, sys.argv[2:])) 
with NamedTemporaryFile('w', delete=False) as outf: 
    with open(sys.argv[1]) as inf: 
     outf.writelines(line for n,line in enumerate(inf, 1) if n not in exclude) 
    os.rename(outf.name, sys.argv[1]) 
+0

Хотя приятное использование 'tempfile',' fileinput' имеет поддержку для простого редактирования на месте, например, в гораздо более чистом коде – jamylak

2
import sys 
# assumes line numbering starts with 1 
# enumerate() starts with zero, so we subtract 1 from each line argument 
omitlines = set(int(arg)-1 for arg in sys.argv[2:] if int(arg) > 0) 
with open(sys.argv[1]) as fp: 
    filteredlines = (line for n,line in enumerate(fp) if n not in omitlines) 
    sys.stdout.writelines(filteredlines) 
1

Модуль fileinput имеет inplace=True вариант, который перенаправляет стандартный вывод в TempFile который автоматически переименованной после вас.

import fileinput 
exclude = set(map(int, sys.argv[2:])) 

for i, line in enumerate(fileinput.input('filename.txt', inplace=True), start=1): 
    if i not in exclude: 
     print line, # fileinput inplace=True redirects stdout to tempfile 
Смежные вопросы