shell-script-pt
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [shell-script] SED: Inserir linhas entre dois paterns.


From: Ronaldo Ferreira de Lima
Subject: Re: [shell-script] SED: Inserir linhas entre dois paterns.
Date: Sat, 11 Oct 2014 23:23:48 -0300
User-agent: mutt-ng/devel-r804 (Linux)

Saudações Rodrigo,

On Sat, Oct 11, 2014 at 09:46:44PM -0300, Rodrigo Tenorio address@hidden 
[shell-script] wrote:
[...]
> Tenho o seguinte cenário:
> 
> cat >> teste << EOT
> LINHAS
> LINHAS
> AAA
> BBB
> LINHAS
> AAA
> EEE
> LINHAS
> LINHAS
> LINHAS
> EOT
> 
> Preciso inserir as linhas BBB, CCC, DDD somente quando a próxima linha de AAA
> for EEE.
> Eu consegui localizar e imprimir com:
> 
> # sed -n "/^AAA/g;{n;/^EEE/p}" teste
Há erros semânticos nesse sed-1liner:

1. '/^AAA/g' => procure por tudo o que começa com "AAA" e não faça
                nada além disto.
2. '{n;' => para cada linha, descarte a atual e coloque a próxima 
            no pattern space.
2.1. '/^EEE/p}' => se a linha começar com "EEE", imprima.       

Aplicando esse comando no exemplo acima, o resultado esperado não é
reproduzido porque o 1liner imprime "EEE" apenas se ele estiver em
linhas pares. Experimente exatamente o mesmo código com o seguinte
exemplo:

1
EEE
3
EEE
5
EEE
7

e você terá três "EEE" como saída.

> Mas ao trocar o "p" para "i BBB" recebo o seguinde retorno:
> 
> # sed -n "/^AAA/g;{n;/^EEE/i BBB}" teste
> sed: -e expressão #1, caractere 0: `{' não terminada
> Acreditava que se eu conseguia imprimir o EEE, eu conseguiria adicionar
> conteúdo antes dele.
Aqui além do problema semântico, há problemas de sintaxe,
precisaria ser reescrito para que o comando "i" fique entre colchetes
(indicando um bloco de comando operando para um endereço), para manter o
1liner, ainda seria necessário utilizar dois '-e'.

> ...
> Bem. Depois de muito bater cabeça, cheguei no ponto em que o sed fez o que eu
> precisava...
> 
> # sed -r ":a;/^AAA/{n;/^EEE/bc};n;ba;:c;i BBB" teste
> 
> ... Mas ainda faltam inserir as linhas CCC e DDD. E isso eu consegui usando "i
> BBB \nCCC \nDDD".
> 
> Destrinchando a coisa da maneira que entendi:
> :a # marcador e início de fluxo de ER.
> /^AAA/ # pesquisa pelo patern AAA que começa com um A, devido ao ^.
> {
> n # pula para a próxima linha.
> /^EEE/ # similar ao /^AAA/.
> bc # salto para o fluxo de ER "c": o "b" é o salto e o "c" é o endereço para
> onde ele vai saltar.
> }
> n # pula para a próxima linha.
> ba # similar ao "bc".
> :c # similar ao ":a".
> i BBB # o "i" insere cadeias de caracteres, na linha imediatamente anterior à
> linha corrente; no caso "BBB".
> É isso.
Esta parte está ok, apenas muito complexa.

> Se eu tiver entendido a coisa errado, se houver ideias complementares; ou se
> houver uma forma melhor de fazer isso, por favor sintam-se livres para
> responder.
Você pode resumir para:

    $ sed '/^AAA$/{n;s/^EEE$/BBB\nCCC\nDDD\n&/}' teste

Para facilitar a visualização do resultado final para este caso, pode-se
usar, por exemplo, um diff -y:

    $ diff -y teste <(sed '/^AAA$/{n;s/^EEE$/BBB\nCCC\nDDD\n&/}' teste)

ou ainda trocar o 'diff -y' por 'vimdiff'.

> Grande abraço,
> Rodrigo Boechat

[]'s
-- 
"Não manejo bem as palavras
Mas manipulo bem as strings."
------------------------------
http://tecnoveneno.blogspot.com


reply via email to

[Prev in Thread] Current Thread [Next in Thread]