#begin command block
#append all lines between two addresses to hold space
sed -n -f - <<\SCRIPT file.xml
\|<tag1>|,\|</tag1>|{ H
#at last line of search block exchange hold and pattern space
\|</tag1>|{ x
#if not conditional ; clear buffer ; branch to script end
\|<tag2>[^<]*foo[^\n]*</tag2>|!{s/.*//;h;b}
#do work ; print result; clear buffer ; close blocks
s?*?*?;p;s/.*//;h;b}}
SCRIPT
Se você fizer o acima, considerando os dados mostrados, antes da última linha de limpeza, você deve estar trabalhando com um espaço de padrão sed
semelhante a:
^\n<tag1>\n<tag2>foo</tag2>\n</tag1>$
Você pode imprimir seu espaço padrão sempre que quiser com l
ook. Você pode então endereçar os caracteres \n
.
sed l <file
Irá mostrar-lhe cada linha sed
processa-a na fase em que l
é chamado.
Então, eu acabei de testá-lo e ele precisou de mais um \backslash
após o ,comma
na primeira linha, mas funciona como está. Aqui eu coloco em um _sed_function
para que eu possa chamá-lo facilmente para fins de demonstração ao longo desta resposta: (funciona com comentários incluídos, mas são removidos aqui por questão de brevidade)
_sed_function() { sed -n -f /dev/fd/3
} 3<<\SCRIPT <<\FILE
\|<tag1>|,\|</tag1>|{ H
\|</tag1>|{ x
\|<tag2>[^<]*foo[^\n]*</tag2>|!{s/.*//;h;b}
s?*?*?;p;s/.*//;h;b}}
#END
SCRIPT
<tag1>
<tag2>bar</tag2>
</tag1>
<tag1>
<tag2>foo</tag2>
</tag1>
FILE
_sed_function
#OUTPUT#
<tag1>
<tag2>foo</tag2>
</tag1>
Agora, alteraremos o p
para um l
, para que possamos ver com o que estamos trabalhando enquanto desenvolvemos nosso script e removemos a demonstração não operacional s?
, para que a última linha de nosso sed 3<<\SCRIPT
apenas se parece com:
l;s/.*//;h;b}}
Então eu vou executá-lo novamente:
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
Ok! Então eu estava certo - isso é uma sensação boa. Agora, vamos embaralhar nosso l
ook para ver as linhas que ele puxa, mas exclui. Removeremos nosso l
atual e adicionaremos um ao !{block}
para que pareça:
!{l;s/.*//;h;b}
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
Isso é o que parece antes de acabarmos com isso.
Uma última coisa que quero mostrar é o espaço H
old conforme o desenvolvemos. Existem alguns conceitos-chave que espero poder demonstrar. Então eu removo o último l
ook novamente e altero a primeira linha para adicionar uma espiada no H
old space no final:
{ H ; x ; l ; x
_sed_function
#OUTPUT#
\n<tag1>$
\n<tag1>\n <tag2>bar</tag2>$
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
\n<tag1>$
\n<tag1>\n <tag2>foo</tag2>$
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
H
old space sobrevive ciclos de linha - daí o nome. Então, o que as pessoas costumam fazer em viagens frequentes - ok, o que eu costuma atrapalhar - é que ele precisa ser excluído depois de usá-lo. Neste caso eu só e x
muda uma vez, então o espaço hold torna-se o espaço padrão e vice-versa e esta mudança também sobrevive aos ciclos de linha.
O efeito é que preciso excluir meu espaço de armazenamento que costumava ser meu espaço de padrão. Eu faço isso primeiro limpando o espaço padrão atual com:
s/.*//
Que simplesmente seleciona todos os caracteres e os remove. Eu não posso usar d
porque isso encerraria meu ciclo de linha atual e o próximo comando não seria concluído, o que praticamente acabaria com meu script.
h
Isso funciona de maneira semelhante a H
, mas substitui o espaço ocupado, então acabei de copiar meu espaço em branco padrão sobre a parte superior do meu espaço de armazenamento, excluindo-o. Agora eu posso apenas:
b
fora.
E é assim que escrevo sed
scripts.