Método bash para ver el comienzo y el final del archivo

8

En los clústeres basados ​​en colas, la cola de trabajos pendientes se muestra desde un comando, por ejemplo showqueue.

El comando devuelve, en columnas, una lista de datos razonables como nombres, etc., pero las columnas / datos realmente no importan para la pregunta.

Me gusta usar la utilidad watchcomo watch showqueuea veces (con un alias de alias watch="watch "forzar la expansión de mi comando para mirar). Hay datos valiosos (trabajos en ejecución), en las primeras líneas, luego trabajos pendientes, etc., y algunos resúmenes valiosos al final.

Sin embargo, a veces la salida de showqueue sale de la pantalla (¡Increíble, lo sé!) Idealmente, me gustaría poder ver el principio y el final del archivo al mismo tiempo.

Lo mejor que tengo hasta ahora es: showqueue > file; head -n 20 file > file2; echo "..." >> file2 ; tail -n 20 file >> file2; cat file2y usar watchun alias de eso.

¿Alguien sabe de algo un poco más flexible o de utilidad única? Mi solución se vuelve un poco más desagradable con los bucles bash para hacer que el "..." se rompa en varias líneas, no se adapta para cambiar el tamaño de la ventana del terminal, y estoy seguro de que hay más que me perdí.

¿Alguna sugerencia?

MadisonCooper
fuente
Cerrado como duplicado, pero la pregunta solo comparte similitudes (la mía es más sobre un comando, aprendí, y no sobre archivos), y las respuestas aquí no aparecieron allí, pero si insiste
MadisonCooper el
2
Lo suficientemente justo. He vuelto a abrir Tenga en cuenta que la respuesta que ha aceptado solo funcionará para salidas grandes, como se señaló en mi respuesta en Command para mostrar las primeras y últimas líneas de un archivo (intente, seq 30 | (head && tail)por ejemplo).
Stéphane Chazelas
2
Quise decir esa respuesta . Ese Q&A tiene dos respuestas mías porque otro Q&A se fusionó con él (ver historial de preguntas )
Stéphane Chazelas

Respuestas:

14

¿Estás buscando hacer algo como lo siguiente? Muestra la salida de la cabeza y la cola.

$ showqueue | (head && tail)
Timothy Pulliam
fuente
66
Algunas implementaciones de headpueden leer más de 10 líneas y no dejan nada para tailleer. No se supone que la utilidad haga eso y creo que las herramientas GNU se comportan bien a este respecto. Úselo head; echo '...'; tailpara poner los puntos allí también.
Kusalananda
Sí, combinado con el comentario de @ Kusalananda es mucho más sucinto que mi solución. ¡Marcaré como correcto por ahora! Gracias.
MadisonCooper
44
@Kusalananda, no, en mi sistema, el cabezal GNU (coreutils 8.26) lee bloques de 8192 bytes. No trate de buscar la espalda, pero, obviamente, no puede, en caso de un tubo. Aunque de todos modos, ¿hay realmente un requisito para headno leer en exceso? (lo mismo en Mac, parece leer por bloques)
ilkkachu
2
@ilkkachu sí, incluso cuando está parado, la parte de la cola está ocasionalmente en blanco, incluso en una salida lo suficientemente larga (lo sé porque estoy usando head -n 35, y eso está lleno), pero afortunadamente es solo una conveniencia de mirar y puedo esperar 3 segundos para una actualización si es necesario.
MadisonCooper
3
@Kusalananda, POSIX permite que las implementaciones hagan eso cuando la entrada no es buscable y la mayoría de las implementaciones lo hacen. No hacerlo significaría leer un byte a la vez, lo que sería muy ineficiente (o volver a colocar los datos en la tubería donde sea compatible, lo que causaría todo tipo de problemas diferentes). La única headimplementación que sé que lee un byte a la vez para evitar leer más allá de la décima línea nueva es la construcción de ksh93 head.
Stéphane Chazelas
2

Usando el mismo enfoque que usted, usando un archivo temporal, pero haciéndolo un poco más corto:

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

Esto no sufriría de los mismos problemas que se discutió bajo otra respuesta , pero sería posible mostrar la misma línea dos veces si la salida fue más corto de 40 líneas.

Kusalananda
fuente
+1 Estaba pensando en la misma solución con la ligera variación de usar teepara dejar que la salida vaya directamente heady solo usar la salida guardada para tail.
Joe
2

Solución awk para un número arbitrario de líneas que se muestran desde la cabeza y la cola (cambie n=3para establecer la cantidad):

$ 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, las partes de la cabeza y la cola no se superpondrán, incluso si la entrada es más corta que las 2*nlíneas.

En algunas implementaciones de awk, el uso for (x in a) print a[x];de la ENDparte también funciona. Pero en general, no se garantiza que devuelva las entradas de la matriz en el orden correcto, y no lo hace, por ejemplo, en mawk.

ilkkachu
fuente
Si mes el número de líneas en el archivo, y m < 2neso imprimirá 2n - mlíneas vacías. También mira aquí ;-). for (x in a)iterará en orden solo en GNU awk ; si crees que también funciona mawk, prueba con> 10 valores.
mosvy
@mosvy, oh, vaya, olvidé volver a comprobar eso después de darme cuenta de que x in ano estaba bien. Solucionado ahora, gracias. También hay otra respuesta awk en la pregunta vinculada a Stéphane. ¡Sin embargo, me gusta el truco del módulo!
ilkkachu
0

Puedes usar un script awk simple. Se agregó un búfer circular allí n = 3 para las últimas 3 líneas

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 )

Sin embargo, después de la actualización ya no es simple,

Abdurrahim
fuente
1
Esto solo mostraría la primera y la última línea. Para mostrar más que eso, tendría que cambiar NR==1a NR <= 10(o algo), y luego recopilar líneas en un búfer (¿circular?) Que luego generará en el ENDbloque.
Kusalananda
sí déjame actualizar
Abdurrahim
Esto imprimirá algunas líneas dos veces cuando el número de líneas sea inferior a 2 * n.
mosvy
:) ok agregando eso también ahora tengo curiosidad por lo que encontrarás a continuación: D
Abdurrahim