У меня есть файл с множеством строк, и каждая строка имеет отметку времени в начале, как
[Thread-3] (21/09/12 06:17:38:672) logged message from code.....
Итак, я часто проверяю 2 вещи из этого файла журнала.
- Первые несколько строк, которые имеют глобальные условия и время начала, также приведены.
- Последние несколько строк, которые имеют статус выхода с некоторой другой информацией.
Есть ли какая-нибудь удобная команда, которая позволила бы мне отображать только первые и последние несколько строк файла?
head and tail
работает для вас?N
sed(1)
эксперт, но есть способы спрятать вещи для дальнейшего использования. Может быть, стоит заглянуть туда. OTOH, я бы, вероятно, взялся за сценарий Perl (или любой другой), чтобы сделать это, если он используется часто, так как я более знаком с этим.Ответы:
Вы можете использовать
sed
илиawk
сделать это с помощью одной команды. Однако вы потеряете в скорости, причиныsed
иawk
нужно будет проходить через весь файл в любом случае. С точки зрения скорости гораздо лучше сделать функцию или каждый раз комбинациюtail
+head
. Недостатком является то, что не работает, если вход представляет собой канал, однако вы можете использовать подстановку процесса, если ваша оболочка это поддерживает (см. Пример ниже).и просто запустить его как
для продолжения процесса подстановки (только bash, zsh, ksh как оболочки):
пс. Вы даже можете добавить,
grep
чтобы проверить, существуют ли ваши «глобальные условия».источник
-n 10
по умолчанию нет?-n 10
здесь не нужно@rush прав в том, что использование head + tail более эффективно для больших файлов, но для маленьких файлов (<20 строк) некоторые строки могут выводиться дважды.
было бы одинаково эффективно, но не было бы проблемы выше.
источник
{head; tail;} < file
работает в Zsh, но не в Sh.{ head; tail;} < file
всегда работает. Извините за шум.head
не с оболочкой. POSIX требуетhead
оставить курсор в файле сразу за этими 10 строками для обычных файлов. Может возникнуть проблема для не-POSIX-head
реализаций (очень старые версии GNU-заголовка раньше были несовместимы в этом случае, но мы говорим десятилетия) или если файл не доступен для поиска (например, именованный канал или сокет, но затем другое решение будет иметь ту же проблему).sudo sh -c '{ head; tail;} < /path/to/file'
{ head; tail; }
Решение не будет работать на трубы (или сокетах или какие - либо другие , не доступных для поиска файлов) , потому чтоhead
может потреблять слишком много данных , как он читает блоки и не может искать назад на трубе потенциально оставляя курсор внутри файла за то , чтоtail
подразумевается выбирать.Таким образом, вы можете использовать инструмент, который читает один символ за раз, например, оболочку
read
(здесь мы используем функцию, которая принимает количество строк заголовка и хвоста в качестве аргументов).или реализовать
tail
в awk, например, как:С
sed
:(хотя имейте в виду, что некоторые
sed
реализации имеют низкое ограничение на размер своего шаблонного пространства, поэтому могут потерпеть неудачу при больших значениях числа хвостовых линий).источник
Используя
bash
процесс подстановки, вы можете сделать следующее:Обратите внимание, что строки не обязательно будут в порядке, хотя для файлов длиннее, чем около 8 КБ, они, скорее всего, будут. Это ограничение 8 КБ является типичным размером буфера чтения и связано с тем, что
| {head; tail;}
он не работает для небольших файлов.Это
cat >/dev/null
необходимо для поддержанияhead
трубопровода в живых. В противном случае онtee
выйдет рано, и пока вы получите выводtail
, он будет где-то посередине ввода, а не в конце.Наконец, почему
>/dev/null
вместо того, чтобы, скажем, перейтиtail
к другому|
? В следующем случае:head
Stdout подается в канал,tail
а не в консоль, а это совсем не то, что нам нужно.источник
tail
он должен работать дольше, но я ожидаю (и вижу), что он потерпит неудачу около половины времени для коротких входных данных.tee >(head) >(tail)
по тем же причинам (>(...)
что, кстати, является функцией ksh, теперь поддерживаемой как zsh, так и bash), также использует каналы. Вы могли бы сделать,... | (trap '' PIPE; tee >(head) >(tail) > /dev/null)
но вы все равно увидите некоторые сообщения об ошибках сломанных трубtee
.tail
SIGPIPE убиваетtee
, аtail
не пишет в канал. Значит, это должно быть от аkill()
? И это происходит только тогда, когда я использую|
синтаксис.strace
говорит, чтоtee
не звонитkill()
... так можетbash
?seq 100000 | tee >(head -n1) >(tail -n1) > /dev/null
Используя
ed
(который прочитает весь файл в RAM все же):источник
ed -s file <<< $'11,$-10d\n,p\nq\n'
Первое решение Стефана в функции, чтобы вы могли использовать аргументы (работает в любой Bourne-подобной или POSIX-оболочке):
Теперь вы можете сделать это:
Это, конечно, предполагает, что вы просматриваете только один файл, и, как решение Стефана, работает (надежно) только с обычными (доступными для поиска) файлами.
источник
С опцией GNU
-u
(--unbuffered
)sed
вы можете использоватьsed -u 2q
в качестве небуферизованной альтернативыhead -n2
:(head -n2;tail -n2)
терпит неудачу, когда последние строки являются частью блока ввода, который используетсяhead
:источник
Сегодня я столкнулся с чем-то вроде этого, где мне понадобилась только последняя строка и несколько строк от начала потока, и я пришел к следующему.
Я читаю это следующим образом: инициализирую пространство удержания с содержимым первой строки, добавляю строки 2-3 в пространство удержания, в EOF добавляю последнюю строку в пространство удержания, меняю пространство удержания и образца и печатаю образец Космос.
Возможно, кто-то с большим
sed
-fu, чем у меня, может понять, как обобщить это, чтобы напечатать последние несколько строк потока, указанного в этом вопросе, но мне это не понадобилось, и я не смог найти простой способ сделать математику на основе$
адреса вsed
или , возможно, управляя трюм так , что только за последние несколько строк в нем , когдаEOF
достигаются.источник
Вы можете попробовать Perl, если он установлен:
Это будет работать для большинства файлов, но считывает весь файл в память перед его обработкой. Если вы не знакомы с фрагментами Perl, «0» в квадратных скобках означает «взять первую строку», а «-3 ...- 1» означает «взять последние три строки». Вы можете адаптировать их обоих к вашим потребностям. Если вам нужно обрабатывать действительно большие файлы (то, что является «большим», может зависеть от вашей оперативной памяти и, возможно, размеров подкачки), вы можете пойти на:
это может быть несколько медленнее, потому что он делает срез на каждой итерации, но это не зависит от размера файла.
Обе команды должны работать как в каналах, так и с обычными файлами.
источник