Распечатайте файл, пропуская первые X строк, в Bash

У меня очень длинный файл, который я хочу напечатать, например, пропустив первые 1 000 000 строк.

Я заглянул на страницу справочника по кошкам, но не нашел возможности сделать это. Я ищу команду для этого или простую программу на Bash.


person Eduardo    schedule 03.03.2009    source источник


Ответы (13)


Вам понадобится хвост. Некоторые примеры:

$ tail great-big-file.log
< Last 10 lines of great-big-file.log >

Если вам действительно нужно пропустить определенное количество «первых» строк, используйте

$ tail -n +<N+1> <filename>
< filename, excluding first N lines. >

То есть, если вы хотите пропустить N строк, вы начинаете печатать строку N + 1. Пример:

$ tail -n +11 /tmp/myfile
< /tmp/myfile, starting at line 11, or skipping the first 10 lines. >

Если вы хотите просто увидеть столько последних строк, опустите "+":

$ tail -n <N> <filename>
< last N lines of file. >
person SingleNegationElimination    schedule 03.03.2009
comment
Или tail --lines = + ‹LinesToSkip› ... для толпы читаемых команд :-) - person paxdiablo; 03.03.2009
comment
в centos 5.6 tail -n +1 показывает весь файл, а tail -n +2 пропускает первую строку. странный. То же для tail -c +<num>. - person NickSoft; 01.09.2011
comment
Ник, ты можешь столкнуться с окончаниями строк в стиле Windows. - person Joel Clark; 28.11.2011
comment
@JoelClark Нет, @NickSoft прав. На Ubuntu это tail -n +<start number>, только что тестировал. Таким образом, tail -n +1 ничего не пропустит, а начнёт с первой строки. - person Andres F.; 22.08.2012
comment
Я могу подтвердить, что tail -n +2 также требуется для пропуска первой строки в Darwin / Mac OS X. - person morgant; 24.03.2014
comment
это должно быть устаревшим, но работает tail -n + 2 OR tail -n +2, как и все короткие команды, использующие getopt, вы можете запустить параметр прямо рядом с его переключателем, при условии, что переключатель является последним в группе, очевидно, что такая команда, как tail -nv + 2, не будет работать, она должна быть tail -vn + 2. если не верите, попробуйте сами. - person osirisgothra; 03.05.2014
comment
В Solaris вам необходимо использовать: /usr/xpg4/bin/tail (нашел это на странице руководства). - person Andrew; 14.09.2017
comment
Думаю, я обнаружил это случайно, но и голова, и хвост позволяют опустить -n, как будто это подразумевается. Вы можете просто <command> | tail +2 - person Lon Kaut; 01.08.2019

Самый простой способ удалить первые десять строк файла:

$ sed 1,10d file.txt

В общем случае (где X - количество начальных строк, которые нужно удалить, за это следует отдать должное комментаторам и редакторам):

$ sed 1,Xd file.txt
person David Parks    schedule 17.10.2012
comment
В более общем случае вам придется использовать sed 1,Xd, где X - количество начальных строк для удаления, причем X больше 1. - person Acumenus; 24.12.2013
comment
Это имеет больше смысла, если вы не знаете, какой длины файл, и не хотите указывать tail на печать последних 100000000 строк. - person springloaded; 29.08.2018
comment
@springloaded, если вам нужно знать количество строк в файле, ‘wc -l’ легко вам его выдаст - person This; 10.06.2020

Если в вашей системе доступен хвост GNU, вы можете сделать следующее:

tail -n +1000001 huge-file.log

Это персонаж +, который делает то, что вы хотите. Цитата из справочной страницы:

Если первый символ K (количество байтов или строк) - это `+ ', печатайте, начиная с K-го элемента с начала каждого файла.

Таким образом, как отмечено в комментарии, при установке +1000001 печать начинается с первого элемента после первых 1 000 000 строк.

person Eddie    schedule 03.03.2009
comment
Работает и для хвоста BSD (OS X) - person Lloeki; 17.11.2016
comment
@Lloeki Замечательно! BSD head не поддерживает отрицательные числа, как это делает GNU, поэтому я предположил, что tail не принимает положительные числа (с +), поскольку это своего рода противоположное. В любом случае, спасибо. - person Joel Mellon; 26.05.2021
comment
Кроме того, чтобы прояснить этот ответ: tail -n +2 huge-file.log пропустит первую строку и перейдет на строку 2. Итак, чтобы пропустить первую строку, используйте +2. Ответ @saipraneeth хорошо объясняет это. - person Joel Mellon; 26.05.2021

Менее подробная версия с AWK:

awk 'NR > 1e6' myfile.txt

Но я бы рекомендовал использовать целые числа.

person newtover    schedule 26.04.2013
comment
полезно, если вам нужно пропустить несколько строк в середине файла, например, awk '!(5 < NR && NR < 10)' - person arekolek; 28.07.2016

Если вы хотите пропустить первые две строки:

tail -n +3 <filename>

Если вы хотите пропустить первую строку x:

tail -n +$((x+1)) <filename>
person saipraneeth    schedule 09.07.2013
comment
Это несколько вводит в заблуждение, потому что кто-то может интерпретировать (x+1) буквально. Например, для x = 2 они могут ввести либо (2+1), либо даже (3), ни один из них не будет работать. Лучше написать это может быть: чтобы пропустить первые X строк, с Y = X + 1, используйте tail -n +Y <filename> - person Acumenus; 24.12.2013

Используйте команду sed delete с адрес диапазона. Например:

sed 1,100d file.txt # Print file.txt omitting lines 1-100.

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

sed -n 201,300p file.txt # Print lines 201-300 from file.txt

Это решение должно надежно работать во всех системах Unix, независимо от наличия утилит GNU.

person maerics    schedule 02.12.2016
comment
Наиболее удобный ответ как для cli, так и для сценариев. - person cerd; 01.12.2017

Если вы хотите увидеть первые 10 строк, вы можете использовать sed, как показано ниже:

sed -n '1,10 p' myFile.txt

Или, если вы хотите увидеть строки с 20 по 30, вы можете использовать:

sed -n '20,30 p' myFile.txt
person Kadir YILDIZ    schedule 20.12.2012

Использовать:

sed -n '1d;p'

Эта команда удалит первую строку и распечатает остальные.

person Soroush Pouryazdian    schedule 03.08.2018
comment
лучше, чем tail imo, так как нам не нужно знать количество строк, которые нужно обрезать. мы просто убираем 1-ю строчку и все - person Tom; 31.01.2020
comment
@Tom вам не нужно знать число в хвосте, чтобы пропустить первую строку, используйте tail +2 - person CervEd; 04.05.2021
comment
действительно хороший момент - person Tom; 04.05.2021

Просто чтобы предложить sed альтернативу. :) Чтобы пропустить первый миллион строк, попробуйте |sed '1,1000000d'.

Пример:

$ perl -wle 'print for (1..1_000_005)'|sed '1,1000000d'
1000001
1000002
1000003
1000004
1000005
person tuomassalo    schedule 26.01.2012
comment
@ Марлон, извини, но это неправильно. Это работает только для 1d. Если, например, вы используете его на 2d, вы удалите только строку 2. Он не удаляет диапазон строк. - person Acumenus; 24.12.2013
comment
@ A-B-B извините, я хотел сказать, что это было самое простое решение, поэтому я +1 не пытался исправить автора. - person Marlon; 14.01.2014

Этот сценарий оболочки отлично подходит для меня:

#!/bin/bash
awk -v initial_line=$1 -v end_line=$2 '{
    if (NR >= initial_line && NR <= end_line) 
    print $0
}' $3

Используется с этим образцом файла (file.txt):

one
two
three
four
five
six

Команда (она будет извлекать со второй по четвертую строку файла):

edu@debian5:~$./script.sh 2 4 file.txt

Вывод этой команды:

two
three
four

Конечно, вы можете улучшить его, например, проверив, что все значения аргументов являются ожидаемыми :-)

person sourcerebels    schedule 31.03.2009
comment
++ для использования awk, который немного более переносим, ​​чем tail - person guns; 31.03.2009

Вы можете сделать это с помощью команд head и tail:

head -n <num> | tail -n <lines to print>

где num равно 1e6 + количество строк, которые вы хотите напечатать.

person Dana the Sane    schedule 03.03.2009
comment
Не самый эффективный ответ, так как вам нужно будет выполнить wc -l в файле, чтобы получить количество строк, а затем добавить миллион :-). Вы можете сделать это с хвостиком. - person paxdiablo; 03.03.2009
comment
Я не уверен, я так понимаю, что 1e6 будет известно во время колла. Однако обратный отсчет - не самый быстрый способ. - person Dana the Sane; 03.03.2009

Мне нужно было сделать то же самое, и я нашел эту ветку.

Я попробовал "tail -n +", но он просто все напечатал.

Строки more + отлично работали в приглашении, но оказалось, что они вели себя совершенно иначе при запуске в режиме без заголовка (cronjob).

Я наконец написал это сам:

skip=5
FILE="/tmp/filetoprint"
tail -n$((`cat "${FILE}" | wc -l` - skip)) "${FILE}"
person Community    schedule 28.05.2009
comment
Правильная ссылка за бесполезное использование кошки. Предыдущее заменяется рекламой. - person kub1x; 26.07.2017
comment
@ kub1x Я не думаю, что кот здесь бесполезен, как кот | wc -l выводит другой результат, чем простой wc -l. Первый подходит для арифметических операций, второй - нет. - person Jack; 15.01.2018
comment
@Jack Я не судил об использовании cat, а только исправлял ссылку в комментарии, которая приводила к мертвой странице. Исходный комментарий должен быть удален. В любом случае, спасибо, что указали на это. - person kub1x; 15.01.2018
comment
@ kub1x Знаете? После прочтения ссылки я думаю, что здесь неправильно использовать cat :) Это должно было быть что-то вроде wc -l ‹$ {FILE}, экономя некоторое время / память (создание нового процесса, конвейерная обработка ввода-вывода, .. ). Спасибо, я узнал кое-что новое - person Jack; 16.01.2018

person    schedule
comment
Это синтаксическая ошибка в bash - в какой оболочке она работает? - person G-Man Says 'Reinstate Monica'; 18.05.2017
comment
Я запускаю это в bash. ‹И› не являются частью команды, имя файла должно заменить ‹File› - person aamadeo; 19.05.2017
comment
awk 'NR > 6 {print}' достаточно ... нет необходимости в if или $ 0. - person CSTobey; 09.01.2019
comment
хорошо, спасибо ! - person Haryono Sariputra; 31.05.2021
comment
На самом деле awk 'NR>6' достаточно, поскольку print является блоком действий по умолчанию :-) См. linuxhandbook.com/awk-command- Учебник для действительно хорошего учебника по awk, который хорошо это объясняет. - person gabrielf; 02.06.2021