Противоположность хвоста: все строки, кроме последних n строк

Как я могу отбросить последние n строк файла с помощью фильтра командной строки unix?

Это было бы своего рода противоположностью tail: tail отбрасывает первые n строк, но передает все остальное, но я хочу, чтобы команда передавала все, кроме последних n строк.

К сожалению, я не нашел ничего подобного - head тоже не помогает. РЕДАКТИРОВАТЬ: по крайней мере в Solaris это не принимает отрицательные аргументы.

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

5 ответов

Решение

Если у вас есть GNU head, ты можешь использовать

head -n -5 file.txt

распечатать все, кроме последних 5 строк file.txt,

Если head -n не принимает отрицательных аргументов, попробуйте

head -n $(( $(wc -l file.txt | awk '{print $1}') - 5 )) file.txt
head file.txt               # first 10 lines
tail file.txt               # last 10 lines
head -n 20 file.txt         # first 20 lines
tail -n 20 file.txt         # last 20 lines
head -20 file.txt           # first 20 lines
tail -20 file.txt           # last 20 lines
head -n -5 file.txt         # all lines except the 5 last
tail -n +5 file.txt         # all lines except the 4 first, starts at line 5

Вот простой способ удалить последнюю строку, которая работает на BSD и т. Д.

sed '$d' input.txt

Выражение гласит "в последней строке, удалите его". Другие строки будут напечатаны, так как это sedповедение по умолчанию.

Вы можете связать их вместе, чтобы удалить несколько строк

sed '$d' input.txt | sed '$d' | sed '$d'

Правда, это немного жестко, но делает только один просмотр файла.

Вы также можете взглянуть на это, чтобы получить дополнительные ответы: https://stackoverflow.com/questions/13380607/how-to-use-sed-to-remove-last-n-lines-of-a-file

Вот одна строка, адаптированная из одного из моих любимых там:

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

Мне было весело расшифровывать это, и я надеюсь, что и вы тоже (: N линии как бы сканирует, но в остальном довольно эффективно.

На MAC решение получения всех строк, кроме последних N строк:

head -n -5 file.txt

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

head: illegal line count -- -5

Одно из решений - установка coreutils и запуск ghead:

brew install coreutils
ghead -n -5 file.txt

GNU Core Utilities или coreutils - это пакет программного обеспечения GNU, содержащий повторные реализации для многих основных инструментов, таких как cat, ls и rm, которые используются в Unix-подобных операционных системах.

Мне любопытно, почему вы думаете head не вариант:

~$ man head
...
-n, --lines=[-]K
        print the first K lines instead of the first 10; 
        with the leading `-', print all but the last K lines of each file

Это, кажется, соответствует вашей цели, используя, например:

head -n -20 yourfile.txt

Еще один способ сделать это, если tail -n не будет принимать отрицательные аргументы

tac file.txt | tail -n +6 | tac

Это удалит последние 5 строк

Другие вопросы по тегам