2012-08-06 17 views
29

¿Existe alguna forma (línea de comando POSIX) de imprimir todo un archivo EXCEPTO las últimas n líneas? Por ejemplo, tendré varios archivos de tamaño desconocido, todos los cuales contienen un pie de página repetitivo de un tamaño conocido, que deseo eliminar. Me preguntaba si ya hay una utilidad que hace esto antes de escribirlo yo mismo.Cola inversa/imprimir todo, excepto las últimas n líneas?

Respuesta

33

La mayoría de las versiones de cabezal (1) - derivadas de GNU, en particular, pero no derivadas de BSD - tienen una función para hacer esto. Mostrará la parte superior del archivo, excepto el final, si usa un número negativo para la cantidad de líneas a imprimir.

así:

head -n -10 textfile 
+8

En POSIX, sin embargo, -n debe ser un entero positivo. – choroba

+1

Lo suficientemente cierto para estrictos POSIX. Debería haber sido más claro con mi "más". Si optas por un método POSIX más rápido y sucio, supongo que 'wc -l' más algunas matemáticas te darán un valor para pasar a' head' –

+0

la mayoría de las implementaciones de head (1) carecen de esta característica. Solo la implementación que conozco tiene este código no portátil. –

4

La utilidad head es su amigo.

Desde la página del manual de head:

-n, --lines=[-]K 
    print the first K lines instead of the first 10; 
     with the leading `-', print all but the last K lines of each file 
+3

En POSIX, sin embargo, -n debe ser un entero positivo. – choroba

+4

Desafortunadamente en sistemas derivados de BSD (es decir, OSX) los valores negativos no son argumentos válidos para -n – Tossrock

0

Si el pie de página comienza con una línea coherente que no aparece en otro lugar, puede utilizar sed:

sed '/FIRST_LINE_OF_FOOTER/q' filename 

Eso imprime la primera línea del pie de página; si se quiere evitar que:

sed -n '/FIRST_LINE_OF_FOOTER/q;p' filename 

Esto podría ser más robusto que las líneas de conteo si el tamaño de los cambios de pie de página en el futuro. (O podría ser menos robusto si la primera línea cambia).

Otra opción, si el comando head de su sistema no es compatible con head -n -10, es precomputar el número de líneas que desea mostrar. El siguiente depende-golpe específico sintaxis:

lines=$(wc -l < filename) ; ((lines -= 10)) ; head -$lines filename 

Obsérvese que la sintaxis head -NUMBER se apoya en algunas versiones de head de compatibilidad hacia atrás; POSIX solo permite el formulario head -n NUMBER. POSIX también solo permite que el argumento -n sea un entero decimal positivo; head -n 0 no es necesariamente un no-op.

solución

Un POSIX es:

lines=$(wc -l < filename) ; lines=$(($lines - 10)) ; head -n $lines filename 

Si usted necesita para hacer frente a los antiguos pre-POSIX conchas, usted podría considerar esto:

lines=`wc -l < filename` ; lines=`expr $lines - 10` ; head -n $lines filename 

Cualquiera de estos puede hacer cosas extrañas si un archivo tiene 10 líneas o menos de longitud.

+0

POSIX tiene la sintaxis '$ (...)' más sana además de los antiguos backticks para la sustitución de comandos, y también tiene el '$ ((...)) 'expansión aritmética. Así que no hay necesidad de volverse antiguo con backticks y 'expr'. [Sustitución del comando POSIX] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03) – geirha

+1

@geirha: Buen punto, y la pregunta hizo específicamente sobre POSIX. Pero conocer la sintaxis antigua puede ser útil en caso de que existan proyectiles anteriores a POSIX aún en uso. –

3

No hay comandos estándar para hacer eso, pero puede usar awk o sed para llenar un búfer de N líneas, e imprimir desde la cabeza una vez que esté lleno. P.ej.con awk:

awk -v n=5 '{if(NR>n) print a[NR%n]; a[NR%n]=$0}' file 
10

Probablemente menos eficiente que el "WC" + Método + "cola" "hacer los cálculos", pero más fácil mirar:

tail -r file.txt | tail +NUM | tail -r 

Dónde NUM es uno más que el número de líneas finales que desea eliminar, por ejemplo +11 imprimirá todas menos las últimas 10 líneas. Esto funciona en BSD que no es compatible con la sintaxis head -n -NUM.

0

Es simple. Debe agregar + a la cantidad de líneas que desea evitar.

Este ejemplo da a que todas las líneas excepto la primera 9

cola -n 10 archivoEntrada

(sí, no es la primera 10 ... pues cuenta diferente ... si quieres 10, simplemente escriba tail -n 11 inputfile)

Cuestiones relacionadas