Замена текста между двумя комментариями HTML

Я новичок в мире sed / awk и regex в целом и изучал их использование, но барахтался, пытаясь удовлетворить мою потребность:

У меня есть страница htm которой есть однострочное уведомление, которое должно быть обновлено с введенным пользователем текстом (через скрипт оболочки) между двумя комментариями, действующими как теги, например:

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

Пользователь, введенный текст (хранящийся в переменной, назовем его $NEWNOTICE ), затем должен будет заменить то, что находится между тегами, так эффективно:

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

Который будет вставлен в файл htm как (например):

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

Как я могу правильно определить и заменить текст между тегами?

2 Solutions collect form web for “Замена текста между двумя комментариями HTML”

Это (совершенно) основной рецепт, который будет отвечать вашим потребностям только точно так:

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

Он будет разбиваться по-разному, если вход отличается, особенно если входной тег разбит на несколько строк.

Использование регулярных выражений обычно не рекомендуется для обработки HTML и XML (я понимаю, что это всего лишь комментарий), но … Если ваш ввод настолько надежен, как намекнул в этом сообщении, то это простое может сделать трюк.

В этом случае я ссылаюсь на части вашего тега как \1 и \3 (которые коррелируют с элементами в скобках в регулярном выражении), чтобы уменьшить количество текста, необходимого для ввода замены.

Или без опции -E и без обратных ссылок:

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

Предполагая, что у вас никогда не будет более одного уведомления в одной строке (точнее, у вас никогда не будет более одного появления <!--BeginNoticeMSG--> или из <!--EndNoticeMSG--> в той же строке):

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

Если комментарии начала и окончания могут отличаться, вы можете написать для них регулярное выражение.

Обратите внимание, что это работает, только если вы уверены, что $NEWNOTICE не содержит \ , & или новую $NEWNOTICE , поскольку в противном случае эти символы интерпретируются как синтаксис sed.

Чтобы быть надежным с символами пунктуации, используйте awk вместо этого.

 export NEWNOTICE awk '{sub(/<!--BeginNoticeMSG-->.*<!--EndNoticeMSG-->/, "<!--BeginNoticeMSG-->" env[NEWNOTICE] "<!--EndNoticeMSG-->"); print}' 
  • эффект * в регулярном выражении
  • Как добавить текущую дату перед расширением файла для нескольких файлов в каталоге?
  • Удалить до заданного символа, начиная с заданной строки
  • эталонная проблема при использовании sed
  • как извлечь часть текста из файла между согласованными условиями
  • эмулировать хвост с sed
  • Заменить многострочную строку в файлах
  • Как заменить строку на точное совпадение строки
  • Как работает эта команда sed?
  • Удалить строку, содержащую определенную строку, и следующую строку
  • Печать строки между двумя круглыми скобками
  • Linux и Unix - лучшая ОС в мире.