Bash метод для просмотра начала и конца файла

8

В кластерах на основе очередей очередь ожидающих заданий отображается из команды, скажем showqueue.

Команда возвращает в столбцах список приемлемых данных, таких как имена и т. Д., Но столбцы / данные не имеют значения для вопроса.

Мне нравится использовать утилиту, watchкак watch showqueueиногда (с псевдонимом, alias watch="watch "чтобы заставить расширение псевдонима моей команды наблюдать). В первых нескольких строках содержатся ценные данные («Выполнение заданий»), затем ожидающие задания и т. Д., А также некоторые ценные сводки в конце.

Однако время от времени вывод showqueue исчезает с экрана (я знаю, это невероятно)! В идеале, я хотел бы, чтобы какой-то способ мог видеть начало и конец файла одновременно.

Лучшее, что у меня есть, - это showqueue > file; head -n 20 file > file2; echo "..." >> file2 ; tail -n 20 file >> file2; cat file2использование watchпсевдонима.

Кто-нибудь знает что-нибудь более гибкое или одноразовое? Мое решение становится немного неприятнее с циклами bash, чтобы сделать разрыв "..." многоуровневым, оно вообще не приспособлено для изменения размера окна терминала, и я уверен, что есть еще кое-что, что я пропустил.

Какие-либо предложения?

MadisonCooper
источник
Закрыто как дубликат, но вопрос имеет только общие черты (у меня есть больше о команде, я узнал, а не файлы), и ответы здесь не отображаются там, но если вы настаиваете
MadisonCooper
2
Справедливо. Я снова открыл Обратите внимание, что ответ, который вы приняли, будет работать только для больших выходных данных, как отмечено в моем ответе на Command, чтобы отобразить первые и последние несколько строк файла (попробуйте, seq 30 | (head && tail)например).
Стефан
2
Я имел в виду этот ответ . У этого Q & A есть два моих ответа, потому что другой Q & A был объединен с ним (см. Историю вопроса )
Стефан

Ответы:

14

Вы хотите сделать что-то вроде следующего? Показывает вывод из головы и хвоста.

$ showqueue | (head && tail)
Тимоти Пулиам
источник
6
Некоторые реализации headмогут читать более 10 строк и ничего не tailчитать. Утилита не должна этого делать, и я считаю, что инструменты GNU хорошо себя ведут в этом отношении. Используйте, head; echo '...'; tailчтобы получить точки там.
Кусалананда
Да, в сочетании с комментарием @ Kusalananda это гораздо более кратко, чем мое решение. Я отмечу как правильный сейчас! Спасибо.
MadisonCooper
4
@Kusalananda, нет, в моей системе глава GNU (coreutils 8.26) считывает блоки по 8192 байта. Он пытается вернуться назад, но, очевидно, не может в случае трубы. Хотя в любом случае, действительно ли есть требование headне перечитывать? (то же самое на Mac, кажется, читает по блокам)
ilkkachu
2
@ilkkachu да, даже несмотря на то, что хвостовая часть иногда пуста даже на достаточно длинном выходе (я знаю, так как использую головку -n 35, и она полная), но, к счастью, это просто удобство для просмотра, и я могу ждать 3 секунды для обновления, если это необходимо.
MadisonCooper
3
@Kusalananda, POSIX позволяет реализациям делать это, когда ввод не доступен для поиска и большинство реализаций делают. Не делать это будет означать чтение одного байта за раз, что будет очень неэффективно (или вернуть данные обратно в канал, где они поддерживаются, что вызовет всевозможные проблемы). Единственная headизвестная мне реализация, которая читает по одному байту за раз, чтобы избежать чтения после 10-го символа новой строки, - это headвстроенная функция ksh93 .
Стефан
2

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

showqueue >/tmp/q.out; head -n 20 /tmp/q.out; echo '...'; tail -n 20 /tmp/q.out

Это не будет страдать от тех же проблем, которые обсуждались в другом ответе , но , возможно, будет показывать одни и те же строки дважды, если результат будет короче 40 строк.

Кусалананда
источник
+1 Я думал о том же решении с небольшим изменением использования, teeчтобы позволить выводу идти прямо headи использовать только сохраненный вывод для tail.
Джо
2

Решение awk для произвольного числа строк, показанных от головы и хвоста (измените, n=3чтобы установить количество):

$ seq 99999 | awk -v n=3 'NR <= n; NR > n { a[NR] = $0; delete a[NR-n]; } 
     END { print "..."; for (i = NR-n+1; i <= NR; i++) if (i in a) print a[i]; }'
1
2
3
...
99997
99998
99999

Как написано, части головы и хвоста не будут перекрываться, даже если ввод короче 2*nлиний.

В некоторых реализациях awk использование for (x in a) print a[x];в ENDчасти также работает. Но в целом, не гарантируется возвращение записей массива в правильном порядке, и это не происходит, например, в mawk.

ilkkachu
источник
Если mэто число строк в файле, и m < 2n, это будет печатать 2n - mпустые строки. Также посмотрите здесь ;-). for (x in a)будет повторяться по порядку только в GNU awk ; если вы думаете, что он mawkтоже работает , протестируйте с> 10 значениями.
Мосви
@mosvy, ой, я забыл еще раз проверить, что после того, как понял, что x in aэто неправильно. Исправлено сейчас, спасибо. В ответе на вопрос Стефана также есть другой ответ на awk . Мне нравится трюк по модулю, хотя!
ilkkachu
0

Вы можете использовать простой скрипт на awk. Добавлен круговой буфер там n = 3 для последних 3 строк

awk 'NR<=n {print $0} { A[NR%n]=$0 } END { for (i=1; i<=n; ++i) if (NR+i>2*n)print A[(NR+i)%n] }' n=3 < <( seq 10 )

После обновления это не так просто,

Абдуррагим
источник
1
Это будет показывать только первую и последнюю строку. Для того, чтобы показать более того, вы должны изменить , NR==1чтобы NR <= 10(или что - то), а затем собирать строки в (циркулярный?) Буфер , который вы позже выход в ENDблоке.
Кусалананда
да, позвольте мне обновить
Абдуррахим
Это напечатает несколько строк дважды, когда количество строк будет меньше 2 * n.
Мосви
:) Хорошо, добавляя, что и сейчас мне интересно, что вы найдете дальше: D
Абдуррахим,