Учитывая dd
считаются слишком опасными для этого на месте удаления линии, нам нужен какой-либо другой метод, где мы имеем достаточно детализированный контроль над файловой системой звонки. Мое первоначальное желание - написать что-то в c, но, по возможности, я думаю, что это немного перебор. Вместо этого стоит посмотреть на обычные сценарии (а не на shell-scripting), так как обычно они имеют довольно низкоуровневые файловые API, которые довольно легко сопоставляются с файловыми системами. Я предполагаю, что это можно сделать с помощью python, perl, Tcl или одного из многих других языков сценариев, которые могут быть доступны. Я больше всего знаком с Tcl, так что здесь мы идем:
#!/bin/sh
# \
exec tclsh "$0" "[email protected]"
package require Tclx
set removeline [lindex $argv 0]
set filename [lindex $argv 1]
set infile [open $filename RDONLY]
for {set lineNumber 1} {$lineNumber < $removeline} {incr lineNumber} {
if {[eof $infile]} {
close $infile
puts "EOF at line $lineNumber"
exit
}
gets $infile line
}
set bytecount [tell $infile]
gets $infile rmline
set outfile [open $filename RDWR]
seek $outfile $bytecount start
while {[gets $infile line] >= 0} {
puts $outfile $line
}
ftruncate -fileid $outfile [tell $outfile]
close $infile
close $outfile
Обратите внимание на моем конкретном поле у меня есть Tcl 8,4, так что мне пришлось загрузить пакет Tclx для того, чтобы использовать ftruncate команды. В Tcl 8.5 есть chan truncate
, который можно использовать вместо этого.
Вы можете передать номер строки, которую хотите удалить, и имя файла для этого скрипта.
Короче говоря, сценарий делает это:
- открыть файл для чтения
- читать первый п-1 строки
- получить смещение начала следующей строки (строка п)
- чтения линии п
- открыть файл с новым FD для написания
- переместить файл местоположения в записи FD на смещение начала строки п
- продолжить чтение оставшихся строк из чтения FD и записывать их на FD записи, пока все прочитанный FD не читается
- усечения записи FD
Файла редактируются точно на месте. Никакие временные файлы не используются.
Я уверен, что это может быть переписано в python или perl или ... если необходимо.
Update
Ok, так что в месте удаления линии может быть сделано в почти чистом Баш, используя те же методы для сценария Tcl выше. Но большой оговоркой является то, что вам нужно иметь команду truncate
. У меня есть это на моей Ubuntu 12.04 VM, но не на моем старшем ядре Redhat. Вот сценарий:
#!/bin/bash
n=$1
filename=$2
exec 3<> $filename
exec 4<> $filename
linecount=1
bytecount=0
while IFS="" read -r line <&3 ; do
if [[ $linecount == $n ]]; then
echo "omitting line $linecount: $line"
else
echo "$line" >&4
((bytecount += ${#line} + 1))
fi
((linecount++))
done
exec 3>&-
exec 4>&-
truncate -s $bytecount $filename
#### or if you can tolerate dd, just to do the truncate:
# dd of="$filename" bs=1 seek=$bytecount count=0
#### or if you have python
# python -c "open(\"$filename\", \"ab\").truncate($bytecount)"
Я хотел бы услышать от более общего (Баш-только?) Способ сделать частичную TRUNCATE в конце и завершить этот ответ. Конечно, усечение можно сделать и с dd
, но я думаю, что это уже было исключено для моего более раннего ответа.
И для записи this site перечислены способы выполнения усечения файла на месте на разных языках - в случае, если любой из них может быть использован в вашей среде.
ред или красный может дать вам то, что вы хотите: HTTP: // ип ix.stackexchange.com/questions/58027/removing-consecutive-newlines-with-ed –
можете ли вы включить свой скрипт awk в этот пост. Я очень удивлен вашим утверждением (кроме * возможно * sun 4's (старый) awk (не nawk)). Удачи. – shellter
У меня нет скрипта awk, который использовался первоначально. Эта инструкция исходит от людей, которые зарабатывают больше денег, чем я ... – user2773624