Saltar al contenido

¿Eliminar líneas antes y después de una coincidencia en bash (con sed o awk)?

Hola, hallamos la respuesta a lo que necesitas, continúa leyendo y la verás más abajo.

Solución:

un awk one-liner puede hacer el trabajo:

awk '/PINITIAL BALANCE/for(x=NR-2;x<=NR+2;x++)d[x];a[NR]=$0ENDfor(i=1;i<=NR;i++)if(!(i in d))print a[i]' file

prueba:

kent$  cat file
######
foo
D28/10/2011
T-3.48
PINITIAL BALANCE
M
x
bar
######
this line will be kept
here
comes
PINITIAL BALANCE
again
blah
this line will be kept too
########

kent$  awk '/PINITIAL BALANCE/for(x=NR-2;x<=NR+2;x++)d[x];a[NR]=$0ENDfor(i=1;i<=NR;i++)if(!(i in d))print a[i]' file
######
foo
bar
######
this line will be kept
this line will be kept too
########

añadir alguna explicación

  awk '/PINITIAL BALANCE/for(x=NR-2;x<=NR+2;x++)d[x];   #if match found, add the line and +- 2 lines' line number in an array "d"
      a[NR]=$0 # save all lines in an array with line number as index
      ENDfor(i=1;i<=NR;i++)if(!(i in d))print a[i]' #finally print only those index not in array "d"
     file  # your input file

sed lo haré:

sed '/n/!N;/n.*n/!N;/n.*n.*PINITIAL BALANCE/$d;N;N;d;P;D'

Funciona de esta manera:

  • si sed tiene solo uno string en el espacio patrón se une a otro
  • si solo hay dos se une al tercero
  • si se ajusta al patrón LINE + LINE + LINE con BALANCE, une dos cadenas siguientes, las elimina y va al principio
  • si no, imprime el primero string del patrón y lo elimina y va al principio sin deslizar el espacio del patrón

Para evitar la aparición de patrones en la primera string debes modificar el script:

sed '1/PINITIAL BALANCE/N;N;d;/n/!N;/n.*n/!N;/n.*n.*PINITIAL BALANCE/$d;N;N;d;P;D'

Sin embargo, falla en caso de que tenga otro PINITIAL BALANCE en string que van a ser eliminados. Sin embargo, otras soluciones también fallan =)

Para tal tarea, probablemente buscaría una herramienta más avanzada como Perl:

perl -ne 'push @x, $_;
          if (@x > 4) 
              if ($x[2] =~ /PINITIAL BALANCE/)  undef @x 
                  else  print shift @x 
          
          END  print @x ' input-file > output-file

Esto eliminará 5 líneas del archivo de entrada. Estas líneas serán las 2 líneas antes del partido, la línea emparejada y las dos líneas posteriores. Puede cambiar el número total de líneas que se eliminan modificando @x > 4 (esto elimina 5 líneas) y la línea que se empareja modificando $x[2] (esto hace que se elimine la coincidencia en la tercera línea y, por lo tanto, elimina las dos líneas anteriores a la coincidencia).

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *