substituição de padrão recursivo de múltiplas linhas

3

A partir da seguinte entrada:

serial0/0
SSL disabled
eth0/0
SSL enabled
SSL only
eth0/1
SSL disabled
bgroup0
SSL enabled
eth0/2
SSL disabled
eth0/3
SSL disabled
eth0/4
SSL disabled
bgroup1
SSL disabled
bgroup2
SSL disabled
bgroup3
SSL disabled
vlan1
SSL enabled
null
SSL disabled

Estou tentando obter uma lista separada por dois pontos na qual, se a próxima linha da entrada começar com "SSL", ela será anexada à linha anterior, portanto, a saída seria assim:

serial0/0:SSL disabled
eth0/0:SSL enabled:SSL only
eth0/1:SSL disabled
bgroup0:SSL enabled
eth0/2:SSL disabled
eth0/3:SSL disabled
eth0/4:SSL disabled
bgroup1:SSL disabled
bgroup2:SSL disabled
bgroup3:SSL disabled
vlan1:SSL enabled
null:SSL disabled

Como você pode ver na segunda linha desta saída ideal, o caso quando mais de uma linha começa com "SSL" deve ser considerado. Com base no este guia clássico sed , criei o seguinte script sed :

sed -r '/^SSL/! {
        :again
        N
        s/(.*)\n(SSL.*)/:/
        t again
    }'

O que faz sentido para mim, mas retorna a seguinte saída:

serial0/0:SSL disabled
eth0/0
SSL enabled
SSL only
eth0/1:SSL disabled
bgroup0
SSL enabled
eth0/2:SSL disabled
eth0/3
SSL disabled
eth0/4:SSL disabled
bgroup1
SSL disabled
bgroup2:SSL disabled
bgroup3
SSL disabled
vlan1:SSL enabled
null
SSL disabled

Alguma ideia do que eu poderia estar fazendo errado?

    
por Luis E 29.08.2016 / 20:01

2 respostas

8

Uma solução muito mais fácil:

sed -z 's/\nSSL/:SSL/g'

O -z diz usar o NUL como um separador de linha - fazendo com que todo o fluxo apareça como uma linha para sed . Em seguida, ele substitui uma sequência \nSSL por uma sequência :SSL , combinando as linhas da maneira que você deseja.

    
por 29.08.2016 / 20:07
4

Você pode fazer isso com qualquer sed de sabor, sem necessidade de fazer o consumo de todo o arquivo na memória. Basta usar um clássico N;P;D cycle e um branch:

sed ':b;$!N;s/\nSSL/:SSL/;tb;P;D' infile

Isso extrai a linha N ext, tenta s ubstitute - se for bem-sucedida, ela retornará para :b else P rints e, em seguida, D será para o caractere de nova linha, reiniciando o ciclo .

    
por 29.08.2016 / 21:20