¿Cómo elimina `awk 'NF {p=1} p'` las líneas en blanco del principio y el final de un archivo?

¿Cómo elimina `awk 'NF {p=1} p'` las líneas en blanco del principio y el final de un archivo?

Buscando una manera de eliminar líneas en blanco desde el principio y el final (usando tac) de un archivo, me topé con esta:

awk 'NF {p=1} p'

¿Cómo/por qué funciona esto?

Lo entiendo NFsolo truesi hay campos (si la línea no es una línea en blanco).

Respuesta1

Esto eliminará las líneas en blanco desde el principio,pero no desde el finalde un archivo.[Aviso: esta respuesta fue escrita antes deleditar a la preguntaque mencionó tac]

Funciona de la siguiente manera:

  • NFes el número de campos encontrados en la línea actual. Si es cero, eso significa que la línea está vacía oblanco, es decir, contiene como máximo espacios en blanco (asumiendo que el separador de campo se deja en su valor predeterminado, donde cualquier número de espacios en blanco consecutivos se considera como separador).
  • La línea actual se imprime si alguna condición fuera de (y no asociada con) los bloques de reglas ( { ... }) se evalúa como true. Inicialmente , la bandera pno está inicializada y se evaluará como false, por lo que a priori no se imprimirá nada.
  • Una vez que se encuentra una línea que no está en blanco ( NFno es cero y se evalúa como ), se ingresa trueal bloque de reglas y se establece el indicador en . Después de eso, el exterior del bloque de reglas se evalúa como y se imprimen las líneas posteriores (incluida la actual, la primera que no está en blanco).{p=1}p1ptrue

Avisoque dado que la bandera pnunca se restablece, cualquier línea en blanco que venga después de la primera línea que no esté en blanco se imprimirá sin filtrar. Si también desea eliminar las líneas en blanco del final, será necesario un método de dos pasadas:

awk 'FNR==NR{if (NF) {if (!first) first=FNR; last=FNR} next}
     FNR>=first && FNR<=last' input.txt input.txt

Esto procesará el archivo dos veces (por lo tanto, se especifica dos veces como operando)

  • En la primera pasada, donde FNRel contador de líneas por archivo es igual a NRel contador de líneas global, identificamos la primera y la última línea que no están en blanco.
  • En la segunda pasada ( FNRahora es más pequeña que NR), solo imprimimos líneas entre (e incluyendo) la primera y la última línea no en blanco así identificadas.

Aviso

Como se indica en elrespuesta de Stéphane Chazelas, el método de dos pasadas sólo funciona con archivos normales. Si su aportación es de naturaleza diferente, consulte el método propuesto allí para encontrar una solución.

Respuesta2

Usando esta técnica para eliminar líneas en blanco tanto del principio como del final del archivo:

awk 'NF {p=1} p' file | # remove blank lines at the file head
  tac |                 # reverse the lines
  awk 'NF {p=1} p' |    # remove blanks from the "new head"
  tac |                 # re-reverse the file
  sponge file           # from the `moreutils` package, to overwrite the file

Respuesta3

Lo que hace su código y por qué solo elimina líneas en blanco al comienzo de la entrada ya se ha explicado enLa respuesta de @AdminBeepor ejemplo, pero aquí para completar, sugeriré un método alternativo para eliminar las líneas en blanco iniciales y finales sin tener que hacer dos pasadas en el archivo (lo que solo funcionaría para archivos normales y no para entradas arbitrarias).

awk '
       NF {print saved $0; saved = ""; started = 1; next}
  started {saved = saved $0 ORS}' < file

Donde retrasamos la impresión de líneas en blanco hasta la siguiente línea que no está en blanco que vemos después (siempre que ya hayamos visto al menos una línea que no esté en blanco antes).

Respuesta4

En caso de que no le importe colocar espacios o tabulaciones en las líneas en blanco que desea conservar, esto eliminará las líneas en blanco del principio y del final:

awk 'NF{for(;c;--c)print "";print;x=1;next} x{++c}'

Cuenta cuántas líneas en blanco aparecen entre líneas que no están en blanco e imprime esa cantidad de líneas vacías antes de cada línea que no está en blanco.

información relacionada