Скажем, у вас есть txt файл, какая команда для одновременного просмотра 10 верхних и нижних 10 строк файла?
то есть. если файл имеет длину 200 строк, то просматривайте строки 1-10 и 190-200 за один раз.
Скажем, у вас есть txt файл, какая команда для одновременного просмотра 10 верхних и нижних 10 строк файла?
то есть. если файл имеет длину 200 строк, то просматривайте строки 1-10 и 190-200 за один раз.
Вы можете просто:
(head; tail) < file.txt
Примечание. Будут напечатаны дублированные строки, если количество строк в файле .txt меньше, чем строки по умолчанию в строке head + default.
ed
является standard text editor
$ echo -e '1+10,$-10d\n%p' | ed -s file.txt
Для чистого потока (например, вывода из команды) вы можете использовать "tee" для форкирования потока и отправки одного потока в голову и от одного до хвоста. Для этого требуется использовать функцию " > (список)" bash (+/dev/fd/N):
( COMMAND | tee /dev/fd/3 | head ) 3> >( tail )
или используя /dev/fd/N (или/dev/stderr) плюс подоболочки со сложным перенаправлением:
( ( seq 1 100 | tee /dev/fd/2 | head 1>&3 ) 2>&1 | tail ) 3>&1
( ( seq 1 100 | tee /dev/stderr | head 1>&3 ) 2>&1 | tail ) 3>&1
(Ни один из них не будет работать в csh или tcsh.)
Для чего-то с немного лучшим контролем вы можете использовать эту команду perl:
COMMAND | perl -e 'my $size = 10; my @buf = (); while (<>) { print if $. <= $size; push(@buf, $_); if ( @buf > $size ) { shift(@buf); } } print "------\n"; print @buf;'
проблема здесь в том, что поточно-ориентированные программы не знают длину файла заранее (потому что может быть не один, если это реальный поток).
инструменты, такие как tail
, буферизуют последние n строк и ждут конца потока, затем печатают.
если вы хотите сделать это в одной команде (и работать с любым смещением и не повторять строки, если они перекрываются), вам придется подражать этому поведению, о котором я говорил.
попробуйте этот awk:
awk -v offset=10 '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' yourfile
Первые 10 строк файла .ext, затем его последние 10 строк:
cat file.ext | head -10 && cat file.ext | tail -10
Последние 10 строк файла, затем первые 10:
cat file.ext | tail -10 && cat file.ext | head -10
Затем вы можете выполнить вывод в другом месте:
(cat file.ext | head -10 && cat file.ext | tail -10 ) | your_program
head -10 file.txt; tail -10 file.txt
Кроме этого, вам нужно будет написать свою собственную программу/ script.
Хорошо, вы всегда можете связать их вместе. Вот так,
head fiename_foo && tail filename_foo
. Если этого недостаточно, вы можете написать себе функцию bash в файле .profile или любом файле входа, который вы используете:
head_and_tail() {
head $1 && tail $1
}
И позже вызовите его из командной строки: head_and_tail filename_foo
.
Почему бы не использовать sed
для этой задачи?
sed -n -e 1,+9p -e 190,+9p textfile.txt
Я написал простое приложение python для этого: https://gist.github.com/garyvdm/9970522
Он обрабатывает каналы (потоки), а также файлы.
Чтобы обрабатывать каналы (потоки), а также файлы, добавьте их в файл .bashrc или .profile:
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' ; }
Тогда вы можете не только
headtail 10 < file.txt
но также
a.out | headtail 10
(Это все еще добавляет ложные пустые строки, когда 10 превышает входную длину, в отличие от обычного старого a.out | (head; tail)
. Спасибо, предыдущие респонденты.)
Примечание: headtail 10
, а не headtail -10
.
опираясь на идеи выше (тестируемые bash и zsh)
но используя псевдоним "шляпа" Head and Tails
alias hat='(head -5 && echo "^^^------vvv" && tail -5) < '
hat large.sql
На основе J.F. Комментарий Себастьяна:
cat file | { tee >(head >&3; cat >/dev/null) | tail; } 3>&1
Таким образом, вы можете обрабатывать первую строку, а остальные - по-разному в одном канале, что полезно для работы с данными CSV:
{ echo N; seq 3;} | { tee >(head -n1 | sed 's/$/*2/' >&3; cat >/dev/null) | tail -n+2 | awk '{print $1*2}'; } 3>&1
N*2 2 4 6
Потребовалось много времени, чтобы закончить это решение, которое, кажется, единственное, что охватывало все варианты использования (пока):
command | tee full.log | stdbuf -i0 -o0 -e0 awk -v offset=${MAX_LINES:-200} \
'{
if (NR <= offset) print;
else {
a[NR] = $0;
delete a[NR-offset];
printf "." > "/dev/stderr"
}
}
END {
print "" > "/dev/stderr";
for(i=NR-offset+1 > offset ? NR-offset+1: offset+1 ;i<=NR;i++)
{ print a[i]}
}'
Список функций:
(sed -u 10q; echo ...; tail) < file.txt
Еще одна вариация темы (head;tail)
, но избегая проблемы с начальной загрузкой буфера для небольших файлов.
Я искал это решение некоторое время. Пробовал сам с sed, но проблема с незнанием длины файла/потока была непреодолимой. Из всех доступных выше вариантов мне понравилось решение Camille Goudeseune awk. Он сделал заметку, что его решение оставило лишние пустые строки на выходе с достаточно небольшим набором данных. Здесь я предоставляю модификацию его решения, которое удаляет дополнительные строки.
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { a_count=0; for (i in a) {a_count++}; for (i=NR-a_count+1; i<=NR; i++) print a[i] }' ; }