使用反向引用在两个模式之间重写 SED 正则表达式

SED Regex rewriting between two patterns using backreferences

我在许多 html 文件中有以下格式的文本:

<!-- BEGIN FOOTER -->
<div id="footer"> 
  <p align="right"> Slogan<br />
    5555 Street East <br />
    City, State 99999 <br />
    Call Us (555)555-5555 <br />
</p>
    
<div align="center">
<a class="footer" href="http://www.example.com" title="Site">Site</a>
</div>


 <br>

</div>
<!--END FOOTER-->

我正在使用这个:

sed -E -i 's/(<!-- BEGIN FOOTER -->)(.|\n)*(<!--END FOOTER-->)/ <br>REPLACE<br>  /m'  file.html

但无法捕获和反向引用它们:

 <!-- BEGIN FOOTER --> 
 <!--END FOOTER--> 

并在它们之间插入:

REPLACE

所以尝试以这样的方式结束:

<!-- BEGIN FOOTER -->
<br>REPLACE<br>
<!--END FOOTER-->

这可能适合您 (GNU sed):

sed '/<!-- BEGIN FOOTER -->/{:a;N;/<!--END FOOTER-->/!ba;s/\n.*\n/\n<br>REPLACE<br>\n/}' file

这会收集页脚之间的线条,并用所需的字符串替换它们之间的线条。

替代方案(类似于 revo);

sed '/<!-- BEGIN FOOTER -->/,/<!--END FOOTER-->/!b;/<!-- BEGIN FOOTER -->/b;/<!--END FOOTER-->/!d;i\<br>REPLACE<br>' file

另一种方式:

sed '/<!-- BEGIN FOOTER -->/,/<!--END FOOTER-->/!b;/<!--END FOOTER-->/p | sed '/<!-- BEGIN FOOTER -->/p;/<!-- BEGIN FOOTER -->/,/<!--END FOOTER-->/c\<br>REPLACE<br>' 

sed 从输入文件中一次读取一行并将结果定向到标准输出。这意味着在输入行中没有要匹配的 \n 字符,除非在某些情况下使用了一些特殊命令。您可以使用地址范围和 insert i 命令来获得所需的输出:

sed '/BEGIN FOOTER/,/END FOOTER/{ /END FOOTER/{i\<br>REPLACE<br>
b}; /BEGIN FOOTER/b; d;}' file

注意第一行后的换行符。 i 在模式 space 中的当前行之前插入数据。 b 跳过剩余的命令,导致新的迭代完成。 /BEGIN FOOTER/,/END FOOTER/ 表示其他命令应执行的范围。

您可以先将BEGIN FOOTEREND FOOTER行保存在begend变量中:

beg=$(grep -n "BEGIN FOOTER" inputfile | cut -d: -f1)
end=$(grep -n "END FOOTER" inputfile| cut -d: -f1)

然后使用sed的c\命令:

sed -i.bak "$((beg+1)),$((end-1))c\<br>REPLACE<br>" inputfile

结果:

<!-- BEGIN FOOTER -->
<br>REPLACE<br>
<!--END FOOTER-->

或者使用单个命令:

sed "/BEGIN FOO/,/END FOO/c\<!--BEGIN FOOTER-->\n<br>REPLACE<br>\n<!--END FOOTER-->" inputfile