2012-02-01 13 views
6

Me han encargado algo bastante doloroso y me preguntaba si alguien podría ayudar.Eliminando bloques de texto del archivo de texto enorme

Nuestro proveedor ha proporcionado un archivo SNMP mib (txt). Desafortunadamente, una gran cantidad de este archivo está desactualizado y debe ser eliminado para nuestra aplicación de monitoreo.

He intentado hacer esto a mano, pero tiene más de 800,000 líneas, y está minando mi deseo de vivir.

La estructura es algo así como:

-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /* Deprecated from: 600.3              */ 
-- /*********************************************************************************/ 

Some text 
some text 
Some text 

-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /*********************************************************************************/ 

Some text 
some text 
Some text 

-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 364.44               */ 
-- /* Deprecated from: 594.3              */ 
-- /*********************************************************************************/ 

repetida hasta el cansancio al azar y ad

Lo que estoy pensando, es un script que:

encuentra el texto "no se utiliza en" luego

delete that line, 
delete the preceding 3 lines, 
delete the following one line, 
delete then all following lines until the next 
"-- /*********************************************************************************/" 

¿Tiene esto sentido? ¿Es posible este tipo de cosas o solo estoy soñando?

Gracias!

+1

Eliminación del 'Deprecated' a la'/** ... 'es bastante fácil, eliminar las 3 líneas anteriores es algo más difícil. – Kevin

+0

Creo que manejar esto con sed o awk me quitaría _mi_ voluntad de vivir. Perl u otro idioma que le permita analizar los límites de la línea es una mejor opción para este problema. –

Respuesta

3

Edit: Me acabo de dar cuenta de que leí su pregunta mal, incluso después de haber sido votado varias veces. ¡Mi respuesta antes estaba fuera! Ahora debería ser más correcto, pero con algunas suposiciones adicionales . ¡Las soluciones simples solo pueden llevarte tan lejos!

Esto podría ser capaz de ayudarle a cabo, con algunas suposiciones:

cat -s data | awk -vFS='\n' -vRS='\n\n' '/Deprecated from/ { getline; next } 1' 

El comando cat es simplemente allí para exprimir el exceso de saltos de línea, por lo awk puede operar con mayor facilidad. En cuanto a awk, -vFS='\n' indica que los campos están separados por líneas nuevas, y -vRS='\n\n' indica que los registros están separados por dos líneas nuevas en una fila. A continuación, /Deprecated from/ encuentra registros que tienen ese texto, y { getline; next } lo lee en el siguiente registro después de él, y hace que se mueva. 1 es un atajo para imprimir líneas que alcanzan el siguiente punto.

Este asumirá la siguiente: bloques

  • todos los comentarios de texto y están separados por al menos una línea en blanco a cada lado
  • Sólo hay bloques de comentarios y bloques de texto intercalados uniformemente
  • No hay líneas en blanco dentro de los bloques de texto

Así que puede que no sea perfecto para usted. Si estas suposiciones son correctas, hace que awk sea una buena opción para este trabajo, como puede ver: ¡el script es muy pequeño!

$ cat -s data | awk -vFS='\n' -vRS='\n\n' '/Deprecated from/ { getline; next } 1' 
-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /*********************************************************************************/ 
Some text 
some text 
Some text 

Además, como puede ver, las líneas nuevas que quedan se expulsan.Para ayudar a esto, se podía modificar el comando de la siguiente manera:

$ cat -s data | awk -vFS='\n' -vRS='\n\n' '/Deprecated from/ { getline; next } { printf "%s\n\n", $0 }' 
-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /*********************************************************************************/ 

Some text 
some text 
Some text 
1

Este es un simple vim macro.

  1. abrir el archivo: $ vim filename
  2. Prensa q a para grabar macros en el registro a
  3. Tipo /Deprecated from: seguido de Enter (para buscar texto)
  4. 3k (para subir 3 líneas)
  5. 4dd (elimine esta línea y la siguiente 3)
  6. d/\*\*\*\*\*\* (para eliminar las líneas hasta los símbolos)
  7. (si es necesario) presione dd (para borrar la línea actual)
  8. Prensa q para finalizar la grabación macro

  9. Tipo [email protected] (para ejecutar la macro un millón de veces)

1

I Estoy muy de acuerdo con el comentario sobre el uso de otro lenguaje de scripting para resolver esto. Ruby, Perl o Python probablemente serían mejores. Pero por diversión, aquí hay un feo script de Awk que lo hace. Los partidos podrían usar algo de trabajo si no son apropiados. Pero es implements una máquina de estado simple. Realiza un seguimiento si está en un encabezado o no y determina si está obsoleto. Almacena las líneas de encabezado en una matriz. Cuando llega al final del encabezado, imprime el encabezado (si no está en desuso). Cuando no está en un encabezado, imprime las líneas si la sección anterior no fue desaprobada.

{ 
    if ($0 ~ /-- \/\**+\//) { 
     # This matches one of the -- /*********...****/ lines 
     if (headercount > 0) { 
     # this must be the closing line in the header 
     if (!deprecated) { 
      for (i = 0; i < headercount; i++) { 
       print headers[i] 
      } 
      # print closing line 
      print 
     } # if not deprecated 

     headercount = 0 
     } 
     else { 
     # must be starting a new section 
     headers[0] = $0 
     headercount = 1 
     deprecated = 0 
     } 
    } 
    else { 
     if (headercount == 0) { 
     # not in a header section - print if not deprecated 
     if (!deprecated) { 
      print 
     } 
     } 
     else { 
     # in a header section - track if it is a deprecated section 
     if ($0 ~ /Deprecated from/) { 
      deprecated = 1 
     } 
     # store the header info to dump when we hit the end 
     headers[headercount++] = $0; 
     } 

    } 
} 
2

Esto podría funcionar para usted:

sed '$!N;$!N;:a;$q;N;/Deprecated from/!{P;s/^[^\n]*\n//;ba};$d;$!N;$d;s/.*//;:b;$d;N;/^\n-- \/\*\+\/$/!{s/.*//;bb};D' file 

Aquí es una solución un poco más fácil (menos eficiente, ya que toma 2 pases):

awk '/Deprecated from/{a=NR-3;getline;next};a>0 && /^-- \/\*+\/$/{b=NR-1;print a "," b "d";a=b=0};END{if(a>0)print a ",$d"}' file | 
sed -f - file 
+0

Lo quiero tanto para que funcione, pero no funciona para mí. No recibo nada impreso. –

+0

@DanFego ¡Ups! dejó una ayuda de depuración. Lo eliminó, intente de nuevo. – potong

+1

¡Es una maraña de letras y símbolos, pero funciona para mí! –

Cuestiones relacionadas