5

Это можно сделать с помощью других инструментов, но мне интересно знать, как я могу удалить все, кроме последних X строк файла, с помощью sed .

4 ответа4

9

В основном ты имитируешь хвост. Х = 20 в этом примере. В следующем примере будут удалены все, кроме последних 20 строк:

sed -e :a -e '$q;N;21,$D;ba' filename

Объяснение:

  • -E:a создает метку, называемую
  • Следующее -е:
    • $ q - выходит и печатает пространство шаблона, если это последняя строка
    • N - следующая строка
    • 21, $ D - выполняет команду "D", если строка #>> = 21 (21, $ = 21-я строка в $, которая является концом файла)
    • ba - ответвления для обозначения "a", которое является началом скрипта.
6

sed довольно сложен, когда дело доходит до такой задачи. tail , grep или awk сделали бы это намного проще и должны использоваться вместо этого. Это , как говорится, это возможно.

Следующее решение адаптировано из sed и Multi-Line Search and Replace.

sed -ni '
    # if the first line copy the pattern to the hold buffer
    1h
    # if not the first line then append the pattern to the hold buffer
    1!H
    # if the last line then ...
    ${
            # copy from the hold to the pattern buffer
            g
            # delete current line if it is followed by at least X more lines
            # replace X-1 with the proper value
            s/.*\n\(\(.*\n\)\{X-1\}\)/\1/
            # print
            p
    }
' filename

Без комментариев это делает изящную однострочную. Если вы хотите исключить, например, все, кроме последних десяти строк, используйте это:

sed -ni '1h;1!H;${;g;s/.*\n\(\(.*\n\)\{9\}\)/\1/;p;}' filename
2

Основываясь на сценарии в разделе 4.13 руководства sed, вы можете сделать что-то вроде этого:

n=10

(( n > 1 )) && script='1h; 2,'$n'{H;g;}; $q; 1,'$((n-1))'d; N; D'
(( n > 1 )) || script='$!d'

sed -i "$script" infile
0

нолики | СЭД | нолики> &&(мв || кот>)

Оба следующих фрагмента команды будут эффективно удалять все, кроме самых последних 5 строк ~/file1 . Если вы хотите сохранить последние 10 строк, вы можете заменить: |sed '1,5!d;' с |sed '1,10!d;' и так далее, как считаете нужным.

  1. tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&mv  "/tmp/file2"  ~/"file1"
  2. tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&cat "/tmp/file2" >~/"file1"

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .