Substituindo texto entre dois comentários em HTML

4

Eu sou novo no mundo de sed / awk e regex em geral e tenho estudado seu uso, mas tenho dificuldades em atender a minha necessidade:

Eu tenho uma página htm que tem um aviso de linha única que precisa ser atualizado com texto inserido pelo usuário (via shell script) entre dois comentários agindo como tags, por exemplo:

<!--BeginNoticeMSG-->NOTICE: This is a notice<!--EndNoticeMSG-->

O texto inserido pelo usuário (armazenado em uma variável, vamos chamá-lo de $NEWNOTICE ) precisaria substituir o que há entre as tags, de forma tão eficaz:

<!--BeginNoticeMSG-->$NEWNOTICE<!--EndNoticeMSG-->

Qual seria inserido no arquivo htm como (por exemplo):

<!--BeginNoticeMSG-->This is a test notice<!--EndNoticeMSG-->

Como posso identificar e substituir o texto entre as tags corretamente?

    
por FFFlow 29.05.2013 / 20:57

2 respostas

3

Esta é uma receita (bastante) básica que atenderá a sua necessidade apenas da forma especificada:

#!/bin/bash
REPLACEWITH="Your replacement text here"
STARTTAG="BeginNoticeMSG"
ENDTAG="EndNoticeMSG"
sed -E "s/(<\!\-\-$STARTTAG\-\->)(.*)(<\!\-\-$ENDTAG\-\->)/$REPLACEWITH/" -i target_file.html

Ele entrará em várias formas diferentes se a entrada for diferente, especialmente se a "tag" de entrada estiver dividida em várias linhas.

Usar expressões regulares normalmente não é recomendado para processar HTML e XML (percebo que isso é apenas um comentário), mas ... Se sua entrada for tão confiável quanto sugerida neste post, algo simples assim poderá fazer o truque .

Neste caso, refiro as partes da sua tag como e (que se correlacionam aos itens entre parênteses na regex) para reduzir a quantidade de texto necessária para digitar a substituição.

Ou sem a opção -E e sem referências anteriores:

#!/bin/bash
REPLACEWITH="Text to replace with here"
STARTTAG="BeginNoticeMSG"
ENDTAG="EndNoticeMSG"
sed -e "s/<\!\-\-$STARTTAG\-\->.*<\!\-\-$ENDTAG\-\->/<\!\-\-$STARTTAG\-\->$REPLACEWITH<\!\-\-$ENDTAG\-\->/" -i target_file.html
    
por 29.05.2013 / 21:16
2

Supondo que você nunca tenha mais de um aviso na mesma linha (mais precisamente, nunca terá mais de uma ocorrência de <!--BeginNoticeMSG--> ou <!--EndNoticeMSG--> na mesma linha):

sed -e "s&\(<!--BeginNoticeMSG-->\).*\(<!--EndNoticeMSG-->\)&$NEWNOTICE&"

Se os comentários iniciais e finais puderem variar, você poderá escrever uma expressão regular para eles.

Observe que isso só funciona se você tiver certeza de que $NEWNOTICE não contém \ , & ou newline, porque senão esses caracteres são interpretados como sintaxe de sed.

Para ser robusto com caracteres de pontuação, use o awk.

export NEWNOTICE
awk '{sub(/<!--BeginNoticeMSG-->.*<!--EndNoticeMSG-->/, "<!--BeginNoticeMSG-->" env[NEWNOTICE] "<!--EndNoticeMSG-->"); print}'
    
por 30.05.2013 / 02:14