Excluindo parte de um arquivo de texto e as seguintes linhas usando sed

8

Preciso editar um arquivo como o seguinte:

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

o objetivo é excluir as linhas que começam com 'iface ... inet6' e também excluir as próximas que começam com espaço (pode ser nenhuma ou mais de uma):

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

e mantenha o restante intacto para o seguinte resultado:

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

Eu tentei com o sed usando o seguinte:

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

mas remove tudo, começando no lugar certo, mas apagando até o fim. Eu só quero remover as linhas que começam com espaço após o texto select iface.

fcm
fonte
1
@ cmd, por favor, deixe-nos saber se as soluções abaixo estão ok. se não podemos ajustá-lo para você
1
@ TNT não é a mesma pergunta. NÃO é para excluir uma única linha, é excluir uma linha mais as seguintes linhas que começam com espaço.
FCM
2
Teoricamente, uma duplicata, mas não na prática - acho que seria bom fornecer uma resposta separada aqui que demonstre como corresponder a partir de um determinado padrão por meio de linhas subseqüentes que possuem espaços em branco à esquerda.
Jeff Schaller
1
O @rudic forneceu uma resposta excelente e elaborada que está longe de ser uma simples pesquisa e exclusão, nada no dup sugerido se aproxima disso.
fcm 17/10

Respostas:

7

Tente esta adaptação do seu sedliner:

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

Corresponde ao intervalo do seu primeiro padrão até a primeira linha NÃO começando com um caractere de espaço e exclui as linhas que começam com espaço ou um "i" (para o início iface). É necessário repensar ise necessário após o bloqueio.

Parece que isso funciona:

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

Por favor, tente reportar.

RudiC
fonte
6

Um script para padrão sedque usa um loop explícito para excluir as linhas:

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

O script localiza as inet6linhas e, em seguida, anexa a próxima linha internamente no espaço do padrão (com um caractere de nova linha incorporado no meio). Em seguida, ele exclui o espaço do padrão até e inclusive o primeiro caractere de nova linha (isso exclui a inet6linha original ). Ele continua fazendo isso até que o espaço do padrão não comece com um caractere em branco (espaço ou tabulação).

Teste:

$ 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

Teste em dados artificiais:

$ 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

O script como "uma linha":

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

Você já tem boas respostas para a sedferramenta, mas deixe-me propor outra abordagem, acredito muito mais simples, usando pcregrep:

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

O regex deve ser auto-explicativo - procuramos o padrão começando na linha ^iface.*inet6e, em seguida, agrupamos qualquer caractere OU nova linha, seguido de um espaço simples repetido zero ou mais vezes. Em seguida, basta instruir pcregreppara permitir a correspondência multi-linear com a -Mopção e inverter a coisa toda por -v(a parte correspondente será removida).

jimmij
fonte
Eu geralmente prefiro usar pcregrep, muito mais intuitivo.
Rui F Ribeiro