Método Bash para visualizar o início e o final do arquivo

8

Em clusters baseados em filas, a Fila de trabalhos pendentes é mostrada em um comando, digamos showqueue.

O comando retorna, em colunas, uma lista de dados razoáveis, como nomes, etc., mas as colunas / dados não são realmente importantes para a pergunta.

Eu gosto de usar o utilitário watchcomo watch showqueueàs vezes (com um apelido de alias watch="watch "forçar o alias de expansão do meu comando para assistir). Existem dados valiosos (Trabalhos em execução), nas primeiras linhas, trabalhos pendentes, etc., e alguns resumos valiosos no final.

No entanto, às vezes a saída do showqueue sai da tela (inacreditável, eu sei)! Idealmente, gostaria de poder ver o início e o fim do arquivo ao mesmo tempo.

O melhor que tenho até agora é:, showqueue > file; head -n 20 file > file2; echo "..." >> file2 ; tail -n 20 file >> file2; cat file2e usando watchum alias disso.

Alguém sabe de algo um pouco mais flexível ou de utilidade única? Minha solução fica um pouco mais desagradável com os loops do bash para tornar a quebra "..." multilineada, não é adaptável ao redimensionamento da janela do terminal, e tenho certeza de que perdi mais.

Alguma sugestão?

MadisonCooper
fonte
Fechada como duplicada, mas a pergunta apenas compartilha semelhanças (a minha é mais sobre um comando, eu aprendi, e não arquivos), e as respostas aqui não apareceram lá, mas se você insistir
MadisonCooper
2
Justo. Eu reabri. Observe que a resposta que você aceitou funcionará apenas para saídas grandes, como observado na minha resposta no Command, para exibir as primeiras e as últimas linhas de um arquivo (tente, seq 30 | (head && tail)por exemplo).
Stéphane Chazelas 26/03/19
2
Eu quis dizer essa resposta . Isso Q & A tem duas respostas minhas porque outro Q & A foi incorporada com ele (ver história pergunta )
Stéphane Chazelas

Respostas:

14

Você está procurando fazer algo como o seguinte? Mostra a saída da cabeça e da cauda.

$ showqueue | (head && tail)
Timothy Pulliam
fonte
6
Algumas implementações de headpodem ler mais de 10 linhas e não deixam nada para tailler. O utilitário não deve fazer isso e acredito que as ferramentas GNU se comportam bem a esse respeito. Use head; echo '...'; tailpara colocar os pontos lá também.
Kusalananda
Sim, combinado com o comentário de @ Kusalananda, é muito mais sucinto do que minha solução. Vou marcar como correto por enquanto! Obrigado.
MadisonCooper
4
@ Kusalananda, não, no meu sistema, o GNU head (coreutils 8.26) lê blocos de 8192 bytes. Ele tenta procurar de volta, mas obviamente não pode no caso de um cano. De qualquer forma, existe realmente um requisito para headnão ler demais? (mesmo no Mac, parece-lido por blocos)
ilkkachu
2
@ilkkachu sim, mesmo que esteja, a parte da cauda está ocasionalmente em branco, mesmo com uma saída suficientemente longa (eu sei desde que estou usando o cabeçote -n 35 e está cheio), mas felizmente é apenas uma conveniência para assistir e posso esperar 3 segundos para uma atualização, se necessário.
MadisonCooper
3
@Kusalananda, o POSIX permite que implementações façam isso quando a entrada não é procurável e a maioria das implementações faz. Não fazer isso significaria ler um byte de cada vez, o que seria muito ineficiente (ou colocar os dados de volta no canal onde suportado, o que causaria todo tipo de problemas diferentes). A única headimplementação que eu sei que lê um byte de cada vez para evitar a leitura da décima nova linha é o built-in do ksh93 head.
Stéphane Chazelas 26/03/19
2

Usando a mesma abordagem que você, usando um arquivo temporário, mas fazendo um pouco mais curto:

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

Isso não sofrem dos mesmos problemas como discutido em outra resposta , mas seria , possivelmente, mostrar as mesmas linhas duas vezes se a saída foi menor do que 40 linhas.

Kusalananda
fonte
+1 Eu estava pensando na mesma solução com a ligeira variação de usar teepara deixar a saída entrar diretamente heade usar apenas a saída salva para tail.
Joe
2

solução awk para um número arbitrário de linhas mostradas da cabeça e da cauda (altere n=3para definir a quantidade):

$ 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

Como está escrito, as partes da cabeça e da cauda não se sobrepõem, mesmo que a entrada seja menor que as 2*nlinhas.

Em algumas implementações do awk, o uso for (x in a) print a[x];da ENDparte também funciona. Mas, em geral, não é garantido o retorno das entradas da matriz na ordem correta, e isso não ocorre, por exemplo, mawk.

ilkkachu
fonte
Se mé o número de linhas no arquivo e m < 2n, isso imprimirá 2n - mlinhas vazias. Também dê uma olhada aqui ;-). for (x in a)irá iterar em ordem somente no GNU awk ; se você acha que também funciona mawk, teste com> 10 valores.
mosvy
@mosvy, oh, opa, eu esqueci de checar novamente depois de perceber que x in anão estava certo. Corrigido agora, obrigado. Há também uma outra resposta estranha na pergunta à qual Stéphane vinculou. Eu gosto do truque do módulo!
22919 ilkkachu
0

Você pode usar um script awk simples. Adicionado buffer de círculo, n = 3 nas últimas 3 linhas

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 )

Depois de atualizar, não é mais simples,

Abdurrahim
fonte
1
Isso mostraria apenas a primeira e a última linha. Para mostrar mais do que isso, você teria que mudar NR==1para NR <= 10(ou algo assim) e, em seguida, coletar linhas em um buffer (circular?) Que você produzirá posteriormente no ENDbloco.
Kusalananda
sim, deixe-me atualizar
Abdurrahim
Isso imprimirá algumas linhas duas vezes quando o número de linhas for menor que 2 * n.
mosvy
:) ok adicionando isso agora também estou curioso para saber o que você encontrará a seguir: D
Abdurrahim