Ответы:
С sed
, вот так:
sed '20,37d; 45d' < input.txt > output.txt
Если вы хотите сделать это на месте:
sed --in-place '20,37d; 45d' file.txt
This option specifies that files are to be edited in-place. GNU
sed 'делает это, создавая временный файл и отправлять вывод в этот файл, а не в стандартный вывод. ... Я не знаю ни о каком другом «sed», но логика обновления «на месте» с помощью потокового редактора не «вычисляет» :)
Если файл удобно помещается в памяти, вы также можете использовать ed
.
Команды очень похожи на приведенную sed
выше, но с одним заметным отличием : вы должны передать список номеров строк / диапазонов, которые должны быть удалены, в порядке убывания (от самой высокой строки / диапазона до самой низкой). Причина в том, что когда вы удаляете / вставляете / разделяете / соединяете строки с ed
, текстовый буфер обновляется после каждой подкоманды, поэтому, если вы удаляете некоторые строки, остальные следующие строки больше не будут находиться в той же позиции в буфере, следующая подкоманда выполнена. Таким образом, вы должны начать назад 1 . Редактирование на
месте :
ed -s in_file <<IN
45d
20,37d
w
q
IN
или
ed -s in_file <<< $'45d\n20,37d\nw\nq\n'
или
printf '%s\n' 45d 20,37d w q | ed -s in_file
Замените w
rite на ,p
rint, если вы хотите напечатать полученный результат вместо записи в файл. Если вы хотите сохранить исходный файл без изменений и записать в другой файл, вы можете передать новое имя файла w
подкоманде rite:
ed -s in_file <<IN
78,86d
65d
51d
20,37d
w out_file
q
IN
1
Если вы не хотите рассчитывать новые номера строк после каждого d
элемента elete, что довольно тривиально для этого конкретного случая (после удаления строк 20-37, т.е. 18 строк, строка 45 становится строкой 27), чтобы вы могли выполнить:
ed -s in_file <<IN
20,37d
27d
w
q
IN
Однако, если вам нужно удалить несколько номеров строк / диапазонов, работать в обратном направлении не составит труда.
q
Полезна ли команда в конце? Я предполагаю, что это выходит так или иначе.
Просто прочитайте это в память, измените это, затем запишите это назад. Вы можете сделать что-то вроде
filename = "foo"
f = open(filename, 'r+')
linenums = [1, 3]
s = [y for x, y in enumerate(f) if x not in [line-1 for line in linenums]]
f.seek(0)
f.write(''.join(s))
f.truncate(f.tell())
f.close()
Протестировано с 5-строчным файлом. Кредиты http://pleac.sourceforge.net/pleac_python/fileaccess.html см. В разделе «Изменение файла на месте без временного файла». Смотрите также /programming/125703/how-do-i-modify-a-text-file-in-python
Некоторые заметки:
Можно сначала обрезать файл, затем записать в него, а не писать, а затем обрезать, как указано выше. Однако я не знаю флага Python, который позволяет читать, а затем выполнять усеченную запись. Но, может быть, я что-то упустил, так как документ не совсем ясен. Что подводит меня к
Иногда документы Python действительно отстой. См. Http://docs.python.org/library/functions.html#open.
Режимы «r +», «w +» и «a +» открывают файл для обновления (обратите внимание, что «w +» усекает файл).
Это что-то значит для тебя? Что, черт возьми, «открыто для обновления»?
Я не знаю, лучше ли делать это в python, в отличие от чего-то юниксного, такого как потоковый редактор. Это может быть более портативным, но я не знаю, как портативный SED. Я просто написал это так, потому что мне удобнее программировать на низком уровне, чем использовать классические инструменты Unix, которые хороши, если они делают именно то, что вы хотите, но (я думаю), как правило, менее гибкие.
Этот подход (манипулирование файлом в памяти) меняет память на дисковое пространство. Он должен нормально работать на машинах с несколькими ГБ памяти для файлов размером до нескольких сотен МБ. Python не очень эффективно обрабатывает строки, поэтому, например, переход на C / C ++ немного повысит производительность и значительно сократит использование памяти.
Вы можете использовать Vim в режиме Ex:
ex -sc '20,37d|45d|x' file
d
удалять
x
сохранить и закрыть