2009-05-18 12 views

Respuesta

12

El truco es almacenar la última línea vista en el "espacio de espera".

sed -n ' 
/^xxxx/{n 
     n 
     x 
     d 
     } 
x 
1d 
p 
${x 
    p 
} 
' <input file> 

A partir de la x - cambiar la línea de entrada actual con el espacio de la bodega (x), a continuación de la primera línea no imprimir nada (1d), las líneas subsiguientes imprimir la línea justo intercambiado desde el espacio de la bodega (p), en la última línea cambie el espacio de retención nuevamente e imprima lo que contenía ($x{x p}. Eso deja qué hacer cuando alcanzamos la línea objetivo (comenzando /^xxxx/) - lea las dos líneas siguientes en el espacio del patrón (n n) y cambie el espacio del patrón con el espacio de espera (x) - esto deja el espacio de espera con la siguiente línea que queremos imprimir y el espacio del patrón con la línea antes del partido, que h que no queremos, por lo que zanja (d)

+0

Una explicación adicional de la 'x' comando que "eXchanges" el espacio del patrón con el búfer de retención: http://www.grymoire.com/Unix/Sed.html#uh-53 –

+0

no puedo ejecutar el script anterior. dice sed: FUNCTION/^ pattern/{n n x d} x 1d p $ {x p} no se puede analizar ¿no está seguro de por qué? –

0

Así es como lo haría en perl, quizás pueda ayudar a encauzarlo por el buen camino ... ¡Buena suerte!

open(INFILE,"<in.txt"); 
my(@arrayOutBoundData, $skipNextLine)l 
for (<INFILE>) { 
    if (not $skipNextLine) { 
     if (/^xxxx$/) { 
      pop(@arrayOutBoundData); 
      $skipNextLine = 1; 
     } else { 
      push(@arrayOutBoundData,$_); 
     } 
    } 
$skipNextLine = 0 
} 

open(OUTFILE,">out.txt"); 
for (@arrayOutBoundData) { 
    print OUTFILE; 
} 

(No se ha probado ninguna Perl en este sistema por favor perdona cualquier sitio sobre.)

1

Se puede extraer de this document. Cubre el uso de sed para trabajar con líneas múltiples.

-1
grep -v -f <(grep -1 "xxxx" file) file 
0

Esto podría funcionar para usted (GNU SED):

echo -e "a\nyyyy\nxxxx\nzzzz\nb" | sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' 
a 
b 

Esto mantiene una ventana de dos líneas en el espacio de patrones y si la expresión regular requerida se encuentra en la primera o segunda línea, lee la siguiente línea y luego elimina las tres líneas. Los casos extremos son si la expresión regular se encuentra en la primera o la última línea cuando no hay línea antes/después. En estos casos, solo se pueden eliminar dos líneas.

Por cierto, esta solución puede haber desenterrado un posible error en GNU sed. El indicador M de una dirección permite utilizar los metacaracteres ^ y $ como marcadores de longitud cero en una expresión regular para el inicio y el final de línea en cadenas de líneas múltiples. La dirección vacía // reutiliza una dirección previamente establecida. ¿Debería esa dirección incluir una bandera multilínea? Actualmente parece incluir la bandera incluso si no se indica es decir

sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' file 

produce una diferente (correcto) dar lugar a:

sed 'N;/^xxxx/M{//d;$!N;d};P;D' file 

si xxxx aparece en la segunda línea de un archivo.

+0

Casi, pero él quiere que zzzz también desaparezca. –

+0

@SamuelEdwinWard solución simple ver edición. – potong

0

Usted puede usar la siguiente:

sed -n '/xxxx/{N;s/.*//;x;d;};x;p;${x;p;}' 

Esto reemplazará 3 líneas con una línea en blanco.

0

primera Puede invertir el archivo, utilice sed para eliminar la línea encajada y la siguiente línea (o líneas, +Nd en sed de comandos), y finalmente revertir el resultado de nuevo:

tac old.file | sed -e '/xxxx/,+1d' | tac > new.file 
Cuestiones relacionadas