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 适合最后一个解决方案,因为如果文件中没有分隔符<!--
,那么它将被完全读入缓冲区。