删除“ ”标签之间的文本,其中“ ”可能位于不同行

删除“ ”标签之间的文本,其中“ ”可能位于不同行

td.txt我有一个包含以下内容的文本文件

More here || <--field="data.com":CHK test text--> || test 2 test x @ -- 
||<!-- more data 
here --> ||
echo "||<!--field="data.com":CHK test text-->|| test 2 test x @ -- ||<--field="data.com":CHK more data here -->|| test data

我希望删除所有实例<!-- and all text inside the tags -->

我有这样的sed表情 cat td.txt | sed 's/<!--[^P]*-->//g'

它确实根据需要删除标签及其内容,但当<!--标签从一行开始并以 . 结尾在另一行时则不会删除-->

使用上述表达式的结果是

More here || <--field="data.com":CHK test text--> || test 2 test x @ -- 
||<!-- more data 
here --> ||
echo "|||| test data

显示

<!-- more data 
    here -->

标签仍然存在

如何删除<!-- and all text inside the tags -->和的所有实例
<!-- and all text
inside the tags -->

使用 sed 或 grep 或任何其他工具?

答案1

要从 XML 文档中删除注释,您可以使用xmlstarlet

xmlstarlet ed -d '//comment()' file.xml

注释是否跨越多行并不重要。

该工具通过其( ) 选项xmlstarlet支持就地编辑。-L--inplace

答案2

我会用perl

perl -0777 -pe 's/<!--.*?-->//sg' < your-file

where-p启用该sed模式,-0777将记录分隔符更改为不可能的字符,这意味着整个文件被作为一条记录处理(slurp 模式),并将正则表达式s///sg的所有匹配项替换为<!--.*?-->空,该s标志.也匹配换行符,并g替换所有发生的事情,而不仅仅是第一次。

它并不关心输入是否是有效的 XML,因为它不会尝试将输入解析为 XML,因此即使输入不是有效的 XML,它也会工作,但从理论上讲,它最终可能会删除那些例如,如果这些<!--或部分-->出现,则不是 XML 注释。<!CDATA[

使用sed,您可以执行类似的操作:

sed ':1
     $!{
       N;b1
     }
     s/_/_u/g; s/(/_</g; s/)/_>/g; # escape _, ( and ) characters
     s/<!--/(/g; s/-->/)/g; # replace <!-- and --> with
                            # single characters ( and )

     s/([^)]*)//g; # remove the comments

     s/)/-->/g; s/(/<!--/g; # revert earlier replacement
     s/_>/)/g; s/_</(/g; s/_u/_/g; # revert earlier escaping'

由于标准sed没有perl的*?运算符( 的非贪婪版本*),因此我们只能使用 using([^)]*)来匹配 on ,(后跟任意数量的字符,而不是))替换了<!--with(-->with后),保存后本身(和字符 )最初在输入中为_<and _>(和_as _u)。

请注意预先将整个输入吸入模式空间的循环(请注意,某些sed实现对模式空间的大小有下限,但 GNU 没有sed)。

答案3

sed '/<!--/!b;:1;/-->/!{N;b1};s/-->/\a/;s/<!--.*\a//' file

<!--标签出现时,我们检查标签是否存在-->,如果不存在,则将该行添加到缓冲区并返回标签 1。用文本文件 、 或 中找不到的字符替换第一个-->标签。从标签中删除到锚点。\r\f\a<!--

让我们把任务复杂化吧。假设多个搜索标签可能同时出现在一行中:

awk 'NR>1 {sub(/-->/,"\r"); sub(/.*\r/, "")}1' RS='<!--' ORS= file

可能只有 GNU awk 适合最后一个解决方案,因为如果文件中没有分隔符<!--,那么它将被完全读入缓冲区。

相关内容