一般来说,我对sed
/和正则表达式的世界很陌生,并且一直在研究它们的用法,但一直在努力满足我的需求:awk
我有一个htm
页面,有一个单行通知,需要使用用户输入的文本(通过 shell 脚本)在两个充当标签的注释之间进行更新,例如:
<!--BeginNoticeMSG-->NOTICE: This is a notice<!--EndNoticeMSG-->
然后,用户输入的文本(存储在变量中,我们称之为$NEWNOTICE
)将需要替换标签之间的内容,因此有效:
<!--BeginNoticeMSG-->$NEWNOTICE<!--EndNoticeMSG-->
它将被插入到htm
文件中(例如):
<!--BeginNoticeMSG-->This is a test notice<!--EndNoticeMSG-->
如何正确识别和替换标签之间的文本?
答案1
这是一个(相当)基本的食谱,只有按照指定的方式才能满足您的需求:
#!/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
答案2
假设您在同一行上从未出现过多个通知(更准确地说,在同一行上从未出现过多次 of<!--BeginNoticeMSG-->
或 of ):<!--EndNoticeMSG-->
sed -e "s&\(<!--BeginNoticeMSG-->\).*\(<!--EndNoticeMSG-->\)&\1$NEWNOTICE\2&"
如果开始和结束注释可能不同,您可以为它们编写正则表达式。
请注意,这仅在您确定$NEWNOTICE
不包含\
,&
或换行符时才有效,因为否则这些字符将被解释为 sed 语法。
为了增强标点符号的鲁棒性,请改用 awk。
export NEWNOTICE
awk '{sub(/<!--BeginNoticeMSG-->.*<!--EndNoticeMSG-->/, "<!--BeginNoticeMSG-->" env[NEWNOTICE] "<!--EndNoticeMSG-->"); print}'