Как использовать sed для удаления последних n строк файла

Я хочу удалить некоторые n строк из конца файла. Можно ли это сделать с помощью sed?

например, чтобы удалить строки от 2 до 4, я могу использовать

$ sed '2,4d' file

но я не знаю номера строк. Я могу удалить последнюю строку, используя

$sed $d file

но я хочу знать, как удалить n строки с конца. Пожалуйста, дайте мне знать, как это сделать, используя sed или какой-либо другой метод.

20 ответов


Я не знаю sed, но это можно сделать с помощью head:

head -n -2 myfile.txt

С sed однострочные:

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

Кажется, то, что вы ищете.


забавный и простой sed и tac устранение :

n=4
tac file.txt | sed "1,$n{d}" | tac

Примечание

  • двойные кавычки " необходимы для оболочки для оценки $n переменная

Если hardcoding n является опцией, вы можете использовать последовательные вызовы sed. Например, чтобы удалить последние три строки, удалите последнюю строку трижды:

sed '$d' file | sed '$d' | sed '$d'

использовать sed, но пусть оболочка делает математику, с целью использования d команда, давая диапазон (чтобы удалить последние 23 строки):

sed -i "$(($(wc -l < file)-22)),$d" file

удалить последние 3 строки, изнутри:

$(wc -l < file)

дает количество строк файла: say 2196

мы хотим удалить последние 23 строки, поэтому для левой стороны или диапазона:

$((2196-22))

выдает: 2174 Таким образом, оригинальный sed после оболочки толкование:

sed -i 2174,$d file

С -i делать inplace edit, файл теперь 2173 строки!


можно использовать глава для этого.

использовать

$ head --lines=-N file > new_file

где N-количество строк, которые вы хотите удалить из файла.

содержимое исходного файла минус последние N строк теперь находятся в new_file


просто для полноты, я хотел бы добавить мое решение. Я закончил тем, что сделал это со стандартным ed:

ed -s sometextfile <<< $'-2,$d\nwq'

этого удалить последние 2 строки, используя редактирование на месте (хотя это тут использовать временный файл в /tmp !!)


Это может сработать для вас (GNU sed):

sed ':a;$!N;1,4ba;P;$d;D' file

для усечения очень больших файлов действительно на месте у нас есть . Он не знает о линиях, но tail + wc можно конвертировать строки в байты:

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

существует очевидное условие гонки, если файл записывается одновременно. В этом случае может быть лучше использовать head - он подсчитывает байты с начала файла (mind disk IO), поэтому мы всегда будем усекать на границе строки (возможно, больше строк, чем ожидалось, если файл активно записывается):

truncate -s $(head -n -$lines $file | wc -c) $file

удобный один-лайнер, если вы не войти попытка поставить пароль вместо имени пользователя:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure

с ответами здесь вы бы уже узнали, что sed не лучший инструмент для этого приложения.

однако я думаю, что есть способ сделать это с помощью sed; идея состоит в том, чтобы добавить N строк, чтобы удерживать пространство, пока вы не сможете читать, не нажимая EOF. При попадании в EOF распечатайте содержимое hold space и завершите работу.

sed -e '$!{N;N;N;N;N;N;H;}' -e x

команда sed выше опустит последние 5 строк.


большинство приведенных выше ответов, похоже, требуют команд/расширений GNU:

    $ head -n -2 myfile.txt
    -2: Badly formed number

чуть более portible решение:

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

или

     perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

или

     awk '{buf[NR-1]=;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

где " 10 "- это"n".


попробуйте выполнить следующую команду:

n = line number
tail -r file_name | sed '1,nd' | tail -r

Вы можете получить общее количество строк с wc -l <file> и использовать

head -n <total lines - lines to remove> <file>


Это можно сделать в 3 шага:

a) подсчитайте количество строк в файле, который вы хотите отредактировать:

 n=`cat myfile |wc -l`

b) вычесть из этого числа количество строк для удаления:

 x=$((n-3))

c) скажите sed удалить из этой строки номер ($x) В конце:

 sed "$x,$d" myfile

Я предпочитаю это решение;

head -$(gcalctool -s $(cat file | wc -l)-N) file

здесь N - это количество строк для удаления.


sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

версия posix


удалить последние 4 строчки:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   

Я придумал это, где n-количество линий, которые вы хотите удалить:

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

это немного окольный путь, но я думаю, что это легко следовать.

  1. подсчитайте количество строк в главном файле
  2. вычесть количество строк, которые вы хотите удалить из графа
  3. распечатайте количество строк, которые вы хотите сохранить и сохранить во временном файле
  4. замените основной файл на временный файл
  5. снимите темп файл

это удалит последние 3 строки из file:

for i in $(seq 1 3); do sed -i '$d' file; done;


это удалит последние 12 строк

sed -n -e :a -e '1,10!{P;N;D;};N;ba'