Что противоположно голове? Я хочу все, кроме первых N строк файла

145

Учитывая текстовый файл неизвестной длины, как я могу прочитать, например, все, кроме первых двух строк файла? Я знаю, tailчто дадут мне последние N строк, но я не знаю, что N впереди.

Итак, для файла

AAAA
BBBB
CCCC
DDDD
EEEE

я хочу

CCCC
DDDD
EEEE

А для файла

AAAA
BBBB
CCCC

Я бы получил просто

CCCC
Николас М. Т. Эллиотт
источник

Ответы:

219

tail --help дает следующее:

  -n, --lines=K            output the last K lines, instead of the last 10;
                           or use -n +K to output lines starting with the Kth

Итак, чтобы отфильтровать первые 2строки, -n +3вы должны получить результат, который вы ищете (начиная с 3-й).

Джо Энос
источник
2
Как ни странно, на моей странице руководства этот параметр не указан, но он отлично работает - спасибо!
Николас М. Т. Эллиотт,
@Nicholas: Странно, я подумал, что это будет стандартная документация вне зависимости от ОС. Я вытащил это из Cygwin внутри Windows, поэтому я не знаю, как это выглядит в различных дистрибутивах Linux. Рад, что это сработало.
Джо Энос,
@NicholasMTElliott man7 перечисляет это как man- страницу Джо Эноса, так что это, вероятно, проблема с версией man-страницы
Ули Кёлер
@SteveJorgensen: Я не понимаю, о чем идет речь в вашем комментарии; никто, кажется, не предлагает использовать headдля этого?
ruakh 05
23

Предполагая, что ваша версия tail поддерживает это, вы можете указать начало хвоста после X строк. В вашем случае вы бы сделали 2 + 1.

tail -n +3

[mdemaria@oblivion ~]$ tail -n +3 stack_overflow.txt
CCCC
DDDD
EEEE
Майк ДеМария
источник
12

Простое решение с использованием awk:

awk 'NR > 2 { print }' file.name
Джанм
источник
Один из нас сбит с толку. В вопросе написано: «все, кроме первых двух строк файла». Как эта команда не соответствует требованиям?
janm
6
{ print }является действием по умолчанию и может быть опущено.
Tripleee
9

Попробуй sed 1,2d. При необходимости замените 2.

lhf
источник
работал как ожидалось .. поскольку количество строк после первых 2 строк неизвестно.
kumarprd
6

tail -n +linecount filenameначнется выход на линии linecountиз filename, так tail -n +3 filename должны делать то , что вы хотите.

Джим Льюис
источник
Это не сработает в моей оболочке, но tail -n +17 filenameбудет. Я использую bash / ubuntu LTS
isomorphismes
2
@iso: Спасибо за предупреждение - более старые версии tailприняли синтаксис, который я использовал в своем исходном ответе, но теперь нужно использовать явную -nопцию. Я соответствующим образом обновил свой ответ.
Джим Льюис
0

Используйте это, предположим, что первый образец называется sample1.dat, тогда он tail --lines=3 sample1.datбудет печатать все строки с 3-й до последней строки.

Для второго примера снова предположим, что он называется sample2.dat, он tail --lines=-1 sample2.datбудет печатать последнюю строку ...

t0mm13b
источник
@ Джим: в чем разница между твоим и моим? .... то же самое ....: o Я имел в виду два примера входных файлов данных в соответствии с его вопросом и показывал, как достичь того, что он искал ... .
t0mm13b
Хорошо ... тогда почему он попросил второй образец и показал желаемый результат, который я использовал 'tail --lines = -1' ... конечно, вы можете полностью опустить имя файла и все равно может действовать как труба ... хм
t0mm13b
@tommie: Ой, забудь, что я сказал о трубах ... Должно быть, я думал о какой-то другой утилите. Но я tail +3 anyfileхотел сказать, что одна команда, дает желаемые результаты для общего случая, в то время как tail --lines=Nтребует заранее знать N, чтобы дать желаемый результат.
Джим Льюис
@tommie: Но это tail... разве это не должно быть "снизу вверх"? (Ба-дум ТИШ! Спасибо, я буду здесь всю неделю ...)
Джим Льюис
0

Я действительно не знаю, как сделать это с помощью хвоста или головы, но с помощью wc -l(количества строк) и выражения bash вы можете этого добиться.

tail -$(( $( wc -l $FILE | grep -Eo '[0-9]+' ) - 2 )) $FILE

Надеюсь это поможет.

NawaMan
источник
1
Это требует полного прохождения файла перед запуском tail. Если размер файла превышает размер памяти, это будет очень неэффективно. Он не обрабатывает файлы менее двух строк. Он не обрабатывает изменение размера файла между wc и tail.
janm
2
@janm: Все в порядке. Другие ответы просто лучше. Мне неловко. :-p
NawaMan
-1

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

awk 'FNR==NR{n=FNR}FNR<=n-3{print}' file file

awk, чтобы получить все, кроме первых двух строк

awk 'NR>2' file

ИЛИ вы можете использовать больше

more +2 file

или просто удар

#!/bin/bash

i=0
while read -r line
do
  [[ $i > 1 ]] && echo "$line"
  ((i++))
done <"file"
призрачная собака74
источник
Теперь это не соответствует требованию. В вопросе говорится «все, кроме первых двух строк файла» и приводятся два примера, каждый с одним файлом, где первые две строки пропускаются, а оставшаяся часть файла отправляется на стандартный вывод. Это не то, что делает эта команда.
janm
да, я неправильно понял вопрос. думал, что он просит все, кроме последних двух строк.
ghostdog74