Eliminar parte de un archivo de texto y seguir líneas usando sed

8

Necesito editar un archivo como el siguiente:

auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
iface wlx000 inet6 auto
  post-up sysctl -w net.ipv6.conf.wlx000.accept_ra=2
auto wlx000

el objetivo es eliminar las líneas que comienzan con 'iface ... inet6' y también eliminar las siguientes que comienzan con espacio (puede ser ninguna o más de una):

iface wlx000 inet6 auto
  post-up sysctl -w net.ipv6.conf.wlx000.accept_ra=2

y mantenga el resto intacto para el siguiente resultado:

auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
auto wlx000

Intenté con sed usando lo siguiente:

sed -i.old -r -e "/iface\s*\w*\s*inet6.*/,\${d;/^\s.*/d;}" /etc/configfile

pero elimina todo comenzando en el lugar correcto pero borrándose hasta el final. Solo quiero eliminar las líneas que miran con espacio después del texto de selección de iface.

fcm
fuente
1
@fcm, háganos saber si las siguientes soluciones están bien. si no podemos
1
Posible duplicado de líneas
1
@TNT no es la misma pregunta. Esto NO es para eliminar una sola línea, es eliminar una línea más las siguientes líneas que miran con espacio.
fcm el
2
Teóricamente un duplicado, pero no en la práctica: creo que sería bueno proporcionar una respuesta por separado aquí que demuestre cómo hacer coincidir un patrón dado con las líneas posteriores que tienen espacios en blanco iniciales.
Jeff Schaller
1
@rudic proporcionó una respuesta excelente y elaborada que está lejos de ser una simple búsqueda y eliminación, nada en el dup sugerido se acerca a eso.
fcm

Respuestas:

7

Pruebe esta adaptación de su sedforro único:

sed  '/iface\s*\w*\s*inet6.*/,/^[^ ]/ {/^[^ i]/!d}' file

Coincide con el rango desde su primer patrón hasta la primera línea que NO comienza con un carácter de espacio, y elimina las líneas que comienzan con espacio o una "i" (para el inicio iface). Es necesario repensar si ise requiere después del bloqueo.

Parece que esto funciona:

sed -n '/iface\s*\w*\s*inet6.*/ {:L; n; /^[ ]/bL;}; p' file

Por favor, intente y vuelva a informar.

RudiC
fuente
6

Un script para estándar sedque usa un bucle explícito para eliminar las líneas:

/^iface .* inet6/ {
    :again
    N
    s/.*\n//
    /^[[:blank:]]/b again
}

El script encuentra las inet6líneas y luego agrega la siguiente línea a esa línea internamente en el espacio del patrón (con un carácter de nueva línea incrustado en el medio). Luego elimina el espacio del patrón hasta el primer carácter de nueva línea (esto elimina la inet6línea original ). Continúa haciendo esto hasta que el espacio del patrón no comience con un carácter en blanco (espacio o tabulación).

Pruebas:

$ cat file
auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
iface wlx000 inet6 auto
  post-up sysctl -w net.ipv6.conf.wlx000.accept_ra=2
auto wlx000
$ sed -f script.sed <file
auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
auto wlx000

Pruebas en datos artificiales:

$ cat file
something1
something2
iface have a inet6 here
   delete me
   me too
   same here
something3
something4
iface more something inet6
   be gone
   skip this
something5
$ sed -f script.sed <file
something1
something2
something3
something4
something5

El guión como "one-liner":

sed -e '/^iface .* inet6/ {' -e ':a' -e 'N;s/.*\n//;/^[[:blank:]]/ba' -e '}'
Kusalananda
fuente
3

Ya tiene buenas respuestas para la sedherramienta, pero permítame proponer otro enfoque, creo que mucho más simple, que utiliza pcregrep:

pcregrep -Mv '^iface.*inet6(.|\n )*' file

La expresión regular debe explicarse por sí misma: buscamos un patrón que comience desde la línea ^iface.*inet6y luego agrupemos cualquier carácter O línea nueva seguida de un espacio simple repetido cero o más veces. Luego solo necesitamos instruir pcregreppara permitir la coincidencia multilineal con la -Mopción y revertir todo -v(se eliminará la parte coincidente).

jimmij
fuente
Generalmente prefiero usar pcregrep, mucho más intuitivo.
Rui F Ribeiro