¿Cómo reemplazo varias líneas con una sola palabra en el archivo (reemplazo in situ)?

9

El contenido de mi filenamearchivo es el siguiente (por ejemplo):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

Quiero reemplazar el bloque de líneas entre STARTy ENDcon una sola palabra, por ejemplo con SINGLEWORD. Como abajo:

My block of line starts from here 
SINGLEWORD
and end to here for example.

Puedo encontrar mi bloque de líneas con este comando:

grep -Pzo "START(.|\n)*END" filename

Y el resultado de ejecutar el comando anterior será así:

START
First line
second line
third line
END

Luego usé este comando para combinar todas las líneas en una sola línea:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

Entonces obtendré este resultado:

START First line second line third line END

Y con mi último comando los LAST_RESULTS | sed 's/.*/SINGLEWORD/'cambio "SINGLEWORD"y obtengo este resultado.

SINGLEWORD

Ahora lo que quiero es: ¿Cómo puedo usar este comando (o el comando de su sugerencia) y reemplazar (en su lugar) mi bloque de líneas a la palabra "SINGLEWORD"? Y el resultado final será como este archivo:

My block of line starts from here 
SINGLEWORD
and end to here for example.
αғsнιη
fuente

Respuestas:

14

Esto se puede hacer muy fácilmente en perl:

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

Explicación

-0 establece el separador de línea en nulo

-paplique el guión dado por -ea cada línea e imprima esa línea

El modificador regexp:

  • /sTratar la cuerda como una sola línea. Es decir, cambiar .para que coincida con cualquier personaje, incluso una nueva línea, que normalmente no coincidiría.

Por qué el ?:

  • De manera predeterminada, un subpatrón cuantificado es "codicioso", es decir, coincidirá tantas veces como sea posible (dada una ubicación de inicio particular) mientras permite que el resto del patrón coincida. Si desea que coincida con el número mínimo de veces posible, siga el cuantificador con a ?.
Sylvain Pineau
fuente
@KasiyA: El uso seddebería ser posible pero probablemente más difícil de leer (Mira esta pregunta )
Sylvain Pineau
Uno más porque mi comienzo y al final patrón tiene caracteres especiales ( /, *, ?) en el mismo y estas son solo ejemplo. y podrías explicar tu orden
αғsнιη
@KasiyA se puede escapar de este tipo de caracteres con \ (exactamente igual que con sed): \/, \*,\?
Sylvain Pineau
@KasiyA lo intenté perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. Debería funcionar
Sylvain Pineau
@KasiyA Creo que ya terminé con las explicaciones;)
Sylvain Pineau
14

Me preguntaba si esto es posible sin perl, pythony otros. Y encontré esta solución usando sed:

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

Explicación:

  1. : a crear una etiqueta 'a'
  2. N agrega la siguiente línea al espacio del patrón
  3. PS si no es la última línea , ba rama (ir a) etiqueta 'a'
  4. s sustituto , /START.*END/por SINGLEWORD, / g coincidencia global (tantas veces como sea posible)

Fue encontrado aquí .

@KasiyA, ¡gracias, aprendí muchas cosas interesantes!

c0rp
fuente